8

I want to set the Expires header for all image/* and text/css. I'm doing this in a Filter. However:

  • before calling chain.doFilter(..) the Content-type is not yet "realized"
  • after calling chain.doFilter(..) the Content-type is set, but so is content-length, which forbids adding new headers (at least in Tomcat implementation)

I can use the extensions of the requested resource, but since some of the css files are generated by richfaces by taking them from inside jar-files, the name of the file isn't x.css, but is /xx/yy/zz.xcss/DATB/....

So, is there a way to get the Content-type before the response is committed.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140

2 Answers2

13

Yes, implement HttpServletResponseWrapper and override setContentType().

class AddExpiresHeader extends HttpServletResponseWrapper {
    private static final long ONE_WEEK_IN_MILLIS = 604800000L;

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

    public void setContentType(String type) {
        if (type.startsWith("text") || type.startsWith("image")) {
            super.setDateHeader("Expires", System.currentTimeMillis() + ONE_WEEK_IN_MILLIS);
        }
        super.setContentType(type);
    }
}

and use it as follows:

chain.doFilter(request, new AddExpiresHeader((HttpServletResponse) response));
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • of course.. I should've thought of this.. especially when using another wrapper in the same filter (for another reason).. :) – Bozho Apr 01 '10 at 20:51
  • (only, it wouldn't be 0, but a time in the future) – Bozho Apr 01 '10 at 20:58
  • no, a `Calendar` - `inTwoMonths.add(Calendar.MONTH, 2);` and then `getTimeInMillis()`. I don't hate the Calendar API that much ;) – Bozho Apr 01 '10 at 21:08
  • This would be a great solution for my problem if I was trying to add a new header; unfortunately I'm trying to modify the value of an existing `Set-Cookie` header and the servlet API provides no way for me to delete cookies. – Dawngerpony Oct 01 '15 at 17:40
2

You should subclass HttpServletResponseWrapper and override addHeader and setHeader to add the newly desired header when "Content-Type" is passed in as the header name. Make sure to not forget to call super in those overridden methods too. Wrap the Response sent in the doFilter method argument with this new Wrapper and pass the Wrapper to the call to doFilter.

laz
  • 28,320
  • 5
  • 53
  • 50
  • (+1) yours and BalusC's answers are both correct solutions, but his is a bit cleaner (at least for me, because a not-so-general method is overridden) – Bozho Apr 01 '10 at 20:52
  • Yes I missed the setContentType method. You might want to consider doing the same for setHeader and addHeader as you never know how it might be coded. Unless of course you own all of the code. – laz Apr 01 '10 at 21:13