Search code examples
javaspringservlet-filterserror-code

OncePerRequestFilter unable to set error code different than 404


I have a Spring application (not using Spring boot) deployed to tomcat

I'm trying to return error 401 (HttpServletResponse.SC_UNAUTHORIZED) on specific URLs in given condition using OncePerRequestFilter ,

But I keep getting Not found error:

Response code: 404

My Filter(removed conditions):

@Component
public class MyFilter extends OncePerRequestFilter {

    private static final Logger logger = Logger.getLogger(MyFilter.class);
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not autorized");           
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            try {
                PrintWriter out = response.getWriter();
                out.write(""); // Empty
                out.flush();
            } catch (IOException e) {
                logger.error("error filtering", e);
            }
            return; // stop chain
    }    
}

I tried using similar code to previous similar answer

I believe you can response.sendError inside do Filter method.

EDIT

If I just throw an exception instead I get a generic error code 500

Response code: 500

EDIT 2

I'm adding filter inside onStartup method overriden WebApplicationInitializer's

FilterRegistration myFilter = servletContext.addFilter("myFilter ", MyFilter.class);
myFilter.addMappingForUrlPatterns(null, false, "/myservlet/myendpoint/*");

EDIT 3

Also my filter in @Componenet and its package include in component scan

@ComponentScan(basePackages = { "my.parent.pacakge"})

Solution

  • I tried your code and it works. Different error codes were getting successfully returned. Although, I wanna point out a couple of things-

    1. The method sendError() sends the response to the client and also clears the response buffer. So, anything you write after it into the response after that is of no use.
    2. Calling setStatus() is of no use either. The HTTP response and HTTP response code has already been sent to the client in the above line when you called sendError().

    Now, this is my hypothesis why your code is not working for you, but it is for me-

    The reason that you might be getting HTTP 404 is that your API is not present. This can be due to a spelling error or maybe due to a simple ignorance like calling your API named /foo/bar like /foo/bar/ i.e. with extra trailing forward slash. I believe that your filter is getting executed successfully and you must be doing something useful there, not the sample code of sendError() that you have explained in the question.

    Also, when you throw an Exception in your filter, the control does not reach to the API and API lookup does not happen. Hence, the default HTTP 500 response is sent to the client due to the unhandled exception instead of HTTP 404.