Enable request logging in Jetty 9.1


Today I wanted to have a more detailed look into the requests coming into one of my applications using Eclipse Jetty. While it is easy enough to see incoming requests by enabling logging for class org.eclipse.jetty.server.Server (via the standard java logging API or SLF4J), adding a method to log incoming request headers is on a different level.

After digging around in the documentation and the sourcecode for a while, this is what I came up with:

// Create a server, but do not start it. This would prevent adding
// handlers later
Server server = JettyHttpContainerFactory.createServer(baseUri, null, null, false);

HandlerCollection handlers = new HandlerCollection();
// request log handler
RequestLogHandler requestLogHandler = new RequestLogHandler();
RequestLog requestLog = new Slf4jRequestLog();
requestLogHandler.setRequestLog(requestLog);
RequestLog traceLog = new Slf4jRequestLog() {
  @Override
  public void log(Request request, Response response) {
	  LOG.info("*************************************");
	  try {
	    Enumeration<String> headerNames = request.getHeaderNames();
	    while(headerNames.hasMoreElements()) {
		    String headerName = headerNames.nextElement();
		    String headerValue = request.getHeader(headerName);
		    LOG.info("{}: {}", headerName, headerValue);
	    }
	    // only dump the request body if we can reset the inputstream
	    if(request.getInputStream().markSupported()) {
		    request.getInputStream().mark(Integer.MAX_VALUE);
		    LOG.info(IOUtils.toString(request.getInputStream()));
		    request.getInputStream().reset();
	    } else {
		    LOG.info("Can not dump request body, because it can not be reset");
	    }
	  } catch (IOException e) {
	    LOG.warn(e);
	  }
	  LOG.info("*************************************");
  }
};
requestLogHandler.setRequestLog(traceLog);
// handler for real requests
final JettyHttpContainer containerHandler = ContainerFactory.createContainer(JettyHttpContainer.class,
	new RestResourceConfigWithSpringSupport("application-context.xml", MyServiceClass.class));
// add all handlers
handlers.setHandlers(new Handler[]{requestLogHandler, containerHandler});
server.setHandler(handlers);

server.start();

Note that I’m using a RestResourceConfigWithSpringSupport, but that doesn’t have to be the case. The main point for me was to create the JettyHttpContainer myself and not use the one created by a different call to JettyHttpContainerFactory.createServer(...). This way I can see at least the HTTP headers coming into my application. I’d prefer to see the body too, but I didn’t want to spent the time for it right now.

If anyone knows a way to wrap the request InputStream into a re-readable option, please let me know.

Weitere Artikel

Dark Mode für Firefox und Thunderbird

Video Thumbnails unter Windows erstellen

Eindrücke aus Red Dead Redemption 2

Neuer Bluray Player: PS4

How to hardware reset the new Oura ring

Neuer Monitor: Dell S2716DG

Ein paar Bilder

Endlich da: Mein Oura Ring

Quick changelog with git

Pik Ass in Destiny 2