Issue
We're currently working on adding headers to each response from our application. To add these headers we're using the Servlet APIs Filter
-interface.
We've got the following filter in our application:
public class SecurityFilter implements Filter
{
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
chain.doFilter(request, response);
HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
httpServletResponse.addHeader("X-Frame-Options", "DENY");
httpServletResponse.addHeader("X-Content-Type-Options", "nosniff");
}
@Override
public void destroy()
{
}
}
This (specifically the doFilter
-method) is implemented correctly according to the documentation, which suggests the following order of work:
- Examine the request
- Optionally wrap the request object with a custom implementation to filter content or headers for input filtering
Optionally wrap the response object with a custom implementation to filter content or headers for output filtering
- Either invoke the next entity in the chain using the FilterChain object (chain.doFilter()),
- or not pass on the request/response pair to the next entity in the filter chain to block the request processing
- Directly set headers on the response after invocation of the next entity in the filter chain.
As far as we can see, the order of our doFilter
-method is correct according to the documentation (pass the request to the chain first as stated under point 4, add custom headers afterwards as stated under point 5). However, the headers we add aren't visible in the responses. If we change to order to the following, everything seems to work just fine:
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
{
HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
httpServletResponse.addHeader("X-Frame-Options", "DENY");
httpServletResponse.addHeader("X-Content-Type-Options", "nosniff");
chain.doFilter(request, response);
}
Can anyone explain this behavior?
Solution
I do not know what version of the Servlet spec are you referring to, but in 3.1, chapter 6.2.1 "Filter Lifecycle" I read (emphasis mine):
- After invocation of the next filter in the chain, the filter may examine response headers.
"Examine" not "set"! Actually, the spec for the header methods says (Servlet 3.1, chapter 5.2 "Headers"):
To be successfully transmitted back to the client, headers must be set before the response is committed. Headers set after the response is committed will be ignored by the servlet container.
I guess this is happening to your request, some servlet or filter down the chain is "committing", so headers are ignored.
Bottom line: The spec (at least as far as I can see in 3.1) does not suggest to set the headers after calling chain.doFilter()
. Your second version that works is correct (and how I've always implemented filters that add headers)!
Answered By - Nikos Paraskevopoulos