views:

814

answers:

2

Is it possible to write a servlet filter to take inspect HTTP response codes?

I want to write a filter that will non-destructively inspect outgoing HTTP response codes. But, there does not seem to be a getResponseCode() like method on the Response object.

It is also not clear to me how unhandled exceptions from the servlet are supposed to be dealt with. I really don't want this filter to actually set anything. Passive is good.

Ideas?

(My other approach involves writing a custom Tomcat valve, but that is not so portable.)

A: 

Would you consider writing a proxy wrapper around the original response class? This way you can handle events / method calls on the object.

stjohnroe
Yes, I am fuzzy on the details. How would unhandled exceptions be handled in this case? Would my proxy wrapper be passed back up the call stack, where it might be possible to change the status code? (I really don't know if this is possible.)
Stu Thompson
+3  A: 

you can wrap your outgoing response using HttpServletResponseWrapper:

class GetStatusWrapper extends HttpServletResponseWrapper {

    private int status;

    GetStatusWrapper(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void setStatus(int sc) {
        super.setStatus(sc);
        status = sc;
    }

    public int getStatus() {
        return status;
    }
}

then in your filter:

public class GetStatusResponseFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, 
                         ServletResponse response, 
                         FilterChain filterChain) 
                            throws IOException, ServletException {
        GetStatusWrapper wrapper;
        wrapper = new GetStatusWrapper((HttpServletResponse) response);
        filterChain.doFilter(request, wrapper);
        System.out.println("status = " + wrapper.getStatus());
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}
dfa
OK, three problems I've come across implementing this: ONE) There are other methods that set the status, but I've got those down (I hope.) TWO) if the status is not explicate set (as is happening in my tests), does that mean i can safely assume it is 200 OK? THREE) What happens if, for example, the super.sendRedirect() throws an error? I'm starting to find this approach overly verbose and do not have confidence that I will capture the SC with authority 100% of the time.
Stu Thompson
1) this is only a "see if it works" implementation. 2) absolutely 3) this is the real problem 4) IMHO there are no other portable approaches as this one; there are only few method that you must override
dfa
OK, it's in production and seems to be working. Thanks. In the end, I initialize int status to 200, override the various setStatus, sendError and sendRedirect method with internal try/catch blocks.
Stu Thompson
you are welcome, can you post somewhere the complete class?
dfa