1

I have a client caching disabling filter which is mapped to all URLs.

Now I have to specifically disable the filter and allow caching when the response has anything other than html.

My current filter code is as follows:

public class NoCacheFilter implements Filter{

    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setHeader("Pragma", "no-cache");
        httpResponse.setHeader("Cache-Control","no-cache,no-store,max-age=0,s-maxage=0,must-revalidate,proxy-revalidate,private,max-stale=0,post-check=0");
        httpResponse.setDateHeader("Expires", 0L);
        filterChain.doFilter(request, response);
    }

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

}

NOTE: Just for people who want to know why I am doing this - We have some paged which generate PDF. We take this PDF File and flush to the output stream. In IE8, the flush code doesn't work and logs show that the client closed the connetion immaturely...Cannot write to committed response.... When caching is enabled, PDF get written to client normally; without any issue. A separate requirement of the existing app is to not allow caching of any page on the client.

Srihari
  • 766
  • 1
  • 6
  • 22
  • take a look at this question: http://stackoverflow.com/questions/1817179/exclude-filter-from-certain-urls the second answer will be helpful – secario Oct 07 '13 at 08:44

2 Answers2

1

Did you try something as simple as this:

@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain filterChain) throws IOException, ServletException {
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    filterChain.doFilter(request, response);
    if(response.getContentType().indexOf("text/html")>-1){
        httpResponse.setHeader("Pragma", "no-cache");
        httpResponse.setHeader("Cache-Control","no-cache,no-store,max-age=0,s-maxage=0,must-revalidate,proxy-revalidate,private,max-stale=0,post-check=0");
        httpResponse.setDateHeader("Expires", 0L);
    }
}

It don't really disable the filter, but at least the filter don't do anything when the response is not html.

ben75
  • 29,217
  • 10
  • 88
  • 134
  • I tried to print the contentType but don't know why for all the responses I get the `contentType=null`. Are you sure that the filter works after the server produces the content? – Srihari Oct 07 '13 at 09:21
  • For all requests, the `response.getContentType()` method return null, but while debugging, I see that `httpResponse.context.contentTypes = [application/binary, application/pdf]`. The said property is a HashSet. Can I access it in any way? – Srihari Oct 07 '13 at 09:41
  • Thanks @NikosParaskevopoulos. Actually I see that the doFilter was on top. Later it was edited. So I am returning it back to the working code and accepting the answer. – Srihari Oct 07 '13 at 09:48
  • This should be correct, with 2 important points: (1) Since response is not a future predicitng machine, put the `if(...)` *after* `filterChain.doFilter()` :) (2) If the content of the response is longer than the response buffer, the headers will be sent and you will not be able to change them after `filterChain.doFilter()`. You should wrap the response in another that will cache the entire content and then, in the filter, unwrap and send it. – Nikos Paraskevopoulos Oct 07 '13 at 09:50
1

Simple, just check in the doFilter() method whether the resource is cacheable or not. You can use the request URI, content-type or MIME type for that.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • Request URI are around 15. That would slow the app down for every request. Content-type of response prints as null. MIME Type is something I am unable to access. – Srihari Oct 07 '13 at 09:36
  • Actually I see the correct `contentType` while debugging in the property `httpResponse.context.contentTypes = [application/binary, application/pdf]`. I am unable to access this HashSet through the defined methods of the object. – Srihari Oct 07 '13 at 09:39