Search code examples
javatomcatservletsembedded-tomcat-7tomcat8

Implement a URL Filter


Simple instance of Embedded Tomcat with a Servlet and a Filter:

            Tomcat tomcat = new Tomcat();
            Context rootCtx = tomcat.addContext("", base.getAbsolutePath());
            FilterDef filterDefinition = new FilterDef();
            filterDefinition.setFilterName(URLFilter.class.getSimpleName());
            filterDefinition.setFilterClass(URLFilter.class.getName());
            rootCtx.addFilterDef(filterDefinition);

            FilterMap filter1mapping = new FilterMap();
            filter1mapping.setFilterName(URLFilter.class.getSimpleName());
            filter1mapping.addURLPattern("/*");
            rootCtx.addFilterMap(filter1mapping);

            Tomcat.addServlet(rootCtx, "Servlet1", new Servlet1());
            rootCtx.addServletMapping("/Servlet1", "Servlet1");

URL Filter Implementation:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
    Boolean filtered = false;
    System.out.println("request intercepted");
    if (request.getAttribute("filtered") != null) {
        filtered = true;
        request.setAttribute("filtered", filtered);
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.sendRedirect("/Servlet1");
        return;
    } else {
        filterChain.doFilter(request, response);
    }
}

For some reason this ends up in an infinite loop and never arrives at Servlet1. What is the correct way of implementing a URL Filter so that I can double check the parameters around the request before delivering the response?


Solution

  • As this solved your problem, posting it as an answer.

    Firstly, you need to ensure that you're either passing the request along the application filter chain, or you're redirecting it:

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filterChain) throws IOException, ServletException {
    
        Boolean filtered = false;
        System.out.println("request intercepted");
        if (!filtered) {
            filtered = true;
            ((HttpServletResponse) response).sendRedirect("/Servlet1");
            return;
        }
    
        filterChain.doFilter(request, response);
    }
    

    Then you need to ensure that the filter knows when an incoming request has already been redirected, so that it doesn't redirect it again:

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filterChain) throws IOException, ServletException {
    
        Boolean filtered = false;
        System.out.println("request intercepted");
        if (request.getAttribute("filtered") != null) {
            filtered = (Boolean) request.getAttribute("filtered");
        }
    
        if (!filtered) {
            request.setAttribute("filtered", Boolean.TRUE);
            ((HttpServletResponse) response).sendRedirect("/Servlet1");
            return;
        }
    
        filterChain.doFilter(request, response);
    }