How can I get the HTTP status code out of a ServletResponse in a ServletFilter?

86,230

Solution 1

First, you need to save the status code in an accessible place. The best to wrap the response with your implementation and keep it there:

public class StatusExposingServletResponse extends HttpServletResponseWrapper {

    private int httpStatus;

    public StatusExposingServletResponse(HttpServletResponse response) {
        super(response);
    }

    @Override
    public void sendError(int sc) throws IOException {
        httpStatus = sc;
        super.sendError(sc);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        httpStatus = sc;
        super.sendError(sc, msg);
    }


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

    public int getStatus() {
        return httpStatus;
    }

}

In order to use this wrapper, you need to add a servlet filter, were you can do your reporting:

public class StatusReportingFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        StatusExposingServletResponse response = new StatusExposingServletResponse((HttpServletResponse)res);
        chain.doFilter(req, response);
        int status = response.getStatus();
        // report
    }

    public void init(FilterConfig config) throws ServletException {
        //empty
    }

    public void destroy() {
        // empty
    }

}

Solution 2

Since Servlet 3.0, there's a HttpServletResponse#getStatus().

So, if there's room for upgrading, upgrade to Servlet 3.0 (Tomcat 7, Glassfish 3, JBoss AS 6, etc) and you don't need a wrapper.

chain.doFilter(request, response);
int status = ((HttpServletResponse) response).getStatus();

Solution 3

Also need to include a wrapper for #sendRedirect, and it would be better to initialize status to '200' rather than '0'

private int httpStatus = SC_OK;

...

@Override
public void sendRedirect(String location) throws IOException {
    httpStatus = SC_MOVED_TEMPORARILY;
    super.sendRedirect(location);
}

Solution 4

One thing missing from David's answer above is that you should also override the other form of sendError:

@Override
public void sendError(int sc, String msg) throws IOException {
    httpStatus = sc;
    super.sendError(sc, msg);
}

Solution 5

In addition to David's answer, you'll also want to override the reset method:

@Override
public void reset() {
    super.reset();
    this.httpStatus = SC_OK;
}

... as well as the deprecated setStatus(int, String)

@Override
public void setStatus(int status, String string) {
    super.setStatus(status, string);
    this.httpStatus = status;
}
Share:
86,230
Seth Weiner
Author by

Seth Weiner

Updated on July 08, 2022

Comments

  • Seth Weiner
    Seth Weiner almost 2 years

    I'm trying to report on every HTTP status code returned from my webapp. However the status code does not appear to be accessible via the ServletResponse, or even if I cast it to a HttpServletResponse. Is there a way to get access to this value within a ServletFilter?

  • David Rabinowitz
    David Rabinowitz almost 14 years
    Thanks William, I've added it to my sample.
  • manuel aldana
    manuel aldana over 11 years
    in case somebody does not read until the end of page, watch out Joel's comment below to also set default status=200 and to also override sendRedirect(..)
  • 1in9ui5t
    1in9ui5t over 11 years
    I can see situations where your filter mapping placement can impact whether your overriding code gets triggered. For example, a successive filter may not wrap your response but rather replace it. Besides those scenarios, can the status code be set on the response without invoking setStatus, sendError or sendRedirect variants? Is that why you've initialized status to 200?
  • user3621633
    user3621633 about 8 years
    This was supremely helpful for an older version of Tomcat that's on Servlet spec 2.4. Thank you!
  • Prasanna Kumar H A
    Prasanna Kumar H A about 8 years
    What about tomcat 6?? servlet version is below 3
  • Prasanna Kumar H A
    Prasanna Kumar H A about 8 years
    Tomcat 6 doesnt support request.getStatus()... what to do for that
  • Junjie
    Junjie about 8 years
    Wonderful! What I need!
  • Prasanna Kumar H A
    Prasanna Kumar H A about 8 years
    response.sendRedirect() is giving illegalStateExcpetion. I have overridded sendRedirect also as Joel's comment
  • Ralph
    Ralph over 7 years
    There is HttpServletRepsone.getStatus() since Servlet 3.0 - see BalusC`s answer: stackoverflow.com/a/4305235/280244
  • Piyush Upadhyay
    Piyush Upadhyay over 4 years
    @Joel Can you please mention why to use SC_OK here? I have faced the same issue where the responseWrapper setStatus() is not invoked and httpStatus remains 0
  • Rocky4Ever
    Rocky4Ever almost 4 years
    But I am getting 0 When i do this.