javajerseyglassfish

How to handle HeaderValueException in Jersey


We have REST endpoints with Jersey + Spring and when we do a request to our endpoint with a malformed header value. For example Accept: application/json/foobar a Exception with HeaderValueException is thrown.

This in return generate a HTML page with a bad request and leaks information about the server we are running.

Looking in jersey code it seems that HeaderValueException is handled different and I cannot seem to make the ExceptionMapper to work with this. (https://jar-download.com/artifacts/org.glassfish.jersey.core/jersey-server/2.7/source-code/org/glassfish/jersey/server/ServerRuntime.java under comment // internal mapping)

We want to return a custom JSON in this particular case.

How do we go about making sure that all exceptions, even HeaderValueException is under our control?

Note: When doing this our endoint is not been called yet..


Solution

  • Jersey ExceptionMappers don't work for this because the request fails earlier in the stack from where the exception mappers can kick in to let you handle the exception. For bad header values for Content-Type header the error response is generated in org.glassfish.jersey.servlet.WebComponent.java see equivalent .

    One way you can handle the error is to implement a Servlet Filter that overrides the Response.SendError() method and that's where you can do custom handling of the error.

    Here's some psuedocode:

    public class MyErrorFilter implements Filter {
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
          HttpServletResponse httpResponse = (HttpServletResponse) response;
    
          HttpServletResponseWrapper modifiedResponse =
              new HttpServletResponseWrapper(httpResponse) {
              @Override
              public void sendError(int sc, String msg) throws IOException {
                  // Custom error handling here.
              }
    
          chain.doFilter(request, modifiedResponse);      
      }
    
    }
    

    Then you can register this filter however you register components in your jersey application, via web.xml or your custom Application class.