package org.dcache.webdav;
import com.google.common.net.InetAddresses;
import dmg.cells.nucleus.CDC;
import org.dcache.util.NetLoggerBuilder;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.security.auth.Subject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.security.cert.X509Certificate;
import static org.dcache.webdav.DcacheResourceFactory.TRANSACTION_ATTRIBUTE;
import static org.dcache.webdav.AuthenticationHandler.DCACHE_SUBJECT_ATTRIBUTE;
public class LoggingHandler extends HandlerWrapper {
private final Logger ACCESS_LOGGER =
LoggerFactory.getLogger("org.dcache.access.webdav");
private static final String X509_CERTIFICATE_ATTRIBUTE =
"javax.servlet.request.X509Certificate";
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
if (isStarted() && !baseRequest.isHandled()) {
super.handle(target, baseRequest, request, response);
int statusCode = response.getStatus();
NetLoggerBuilder log = new NetLoggerBuilder(logLevel(statusCode),
"org.dcache.webdav.request").omitNullValues();
log.add("session", CDC.getSession());
log.add("transaction", getTransaction(request));
log.add("request.method", request.getMethod());
log.add("request.url", request.getRequestURL());
log.add("response.code", statusCode);
log.add("response.reason", getReason(response));
log.add("location", response.getHeader("Location"));
InetAddress addr = InetAddresses.forString(request.getRemoteAddr());
log.add("socket.remote", new InetSocketAddress(addr, request.getRemotePort()));
log.add("user-agent", request.getHeader("User-Agent"));
log.add("user.dn", getCertificateName(request));
log.add("user.mapped", getSubject(request));
log.toLogger(ACCESS_LOGGER);
}
}
private static String getReason(HttpServletResponse response)
{
if (response instanceof Response) {
return ((Response) response).getReason();
} else {
return HttpStatus.getMessage(response.getStatus());
}
}
private static NetLoggerBuilder.Level logLevel(int code) {
if (code >= 500) {
return NetLoggerBuilder.Level.ERROR;
} else if (code >= 400) {
return NetLoggerBuilder.Level.WARN;
} else {
return NetLoggerBuilder.Level.INFO;
}
}
private static String getCertificateName(HttpServletRequest request) {
Object object = request.getAttribute(X509_CERTIFICATE_ATTRIBUTE);
if (object instanceof X509Certificate[]) {
X509Certificate[] chain = (X509Certificate[]) object;
if (chain.length >= 1) {
return chain[0].getSubjectX500Principal().getName();
}
}
return null;
}
private static String getTransaction(HttpServletRequest request) {
Object object = request.getAttribute(TRANSACTION_ATTRIBUTE);
return object == null ? null : String.valueOf(object);
}
private static Subject getSubject(HttpServletRequest request) {
Object object = request.getAttribute(DCACHE_SUBJECT_ATTRIBUTE);
return (object instanceof Subject) ? (Subject) object : null;
}
}