Carmine Giangregorio Carmine Giangregorio - 17 days ago 5
Java Question

Jetty and Dropwizard: how to return always 200 instead of 404, 500, etc

I'm using Dropwizard 0.8.0 that comes with Jetty-Jersey-Jackson stack.

For security reasons, I want to add a filter that makes every request that passes through a particular route defined with Jersey returns always 200, even in case of error (4xx, 5xx, etc.).

Is this possibile with Jetty/Servlet filters? Can I intercept the request after it passed through Jersey resource (the controller), but before it is returned to client, in order to modify the http status code?

UPDATE:

I'm trying to do this with a ServletFilter, but it seems that the response is sent to client before my code is executed.

I've written the filter this way:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (response instanceof HttpServletResponse) {
/* No pre-processing */

chain.doFilter(request, response);

/* Post-processing: */

HttpServletResponse modifiedResponse = (HttpServletResponse) response;

if (modifiedResponse.getStatus() != 200) {
modifiedResponse.setStatus(200);
}
}
}


With this, registered in Dropwizard with:

environment.servlets().addFilter("MyCustomFilter", new MyCustomFilter())
.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/mypath/*");


The filter is executed, and in the access.log I see all the requests with status code 200; but the client always get the "real" status code (ex, a 404, or a "Method not allowed").

It seems that the response is sent to client before the last part of filter is executed. Moreover, I can't modify the response body. I tried also with a HttpServletResponseWrapper, but with no luck.

Answer

I'm updating the question with my solution that finally works: I've used a Jersey filter instead of a Jetty http filtering, in order to manage directly the Response object from Jersey.

Obviously, this works only if you're using Jetty+Jersey, not with Jetty stand-alone.

Here's the filter I'm using:

/**
 * When active, this filter transforms all responses for specified basePath to 200, even in case of error.
 */
@Provider
public class DiscardErrors implements ContainerResponseFilter
{
    private String basePath;

    public DiscardErrors(String basePath)
    {
        this.basePath = basePath;
    }

    @Override
    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) throws IOException
    {
        if containerRequestContext.getUriInfo().getPath().startsWith(this.basePath) {
            if (containerResponseContext.getStatus() != 200) { // Check if response code is different from 200
                containerResponseContext.setStatus(200); // Force 200 status code
                containerResponseContext.setEntity(""); // Empty body
            }
        }
    }

}

And register it in Dropwizard:

environment.jersey().register(new DiscardErrors("/"));
Comments