views:

44

answers:

1

Does anyone know how to go about coding a servlet filter that will set cache headers on a response for a given file/content type? I've got an app that serves up a lot of images, and I'd like to cut down on bandwidth for hosting it by having the browser cache the ones that don't change very often. Ideally, I'd like to be able to specify a content type and have it set the appropriate headers whenever the content type matches.

Does anyone know how to go about doing this? Or, even better, have sample code they'd be willing to share? Thanks!

+4  A: 

In your filter have this line:

chain.doFilter(httpRequest, new AddExpiresHeaderResponse(httpResponse));

Where the response wrapper looks like:

class AddExpiresHeaderResponse extends HttpServletResponseWrapper {

    public static final String[] CACHEABLE_CONTENT_TYPES = new String[] {
        "text/css", "text/javascript", "image/png", "image/jpeg",
        "image/gif", "image/jpg" };

    static {
        Arrays.sort(CACHEABLE_CONTENT_TYPES);
    }

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

    @Override
    public void setContentType(String contentType) {
        if (contentType != null && Arrays.binarySearch(CACHEABLE_CONTENT_TYPES, contentType) > -1) {
            Calendar inTwoMonths = GeneralUtils.createCalendar();
            inTwoMonths.add(Calendar.MONTH, 2);

            super.setDateHeader("Expires", inTwoMonths.getTimeInMillis());
        } else {
            super.setHeader("Expires", "-1");
            super.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        }
        super.setContentType(contentType);
    }
}

In short, this creates a response wrapper, which, on setting the content type, adds the expires header. (If you want, you can add whatever other headers you need as well). I've been using this filter + wrapper and it works.

See this question on one specific problem that this solves, and the original solution by BalusC.

Bozho
Alternatively, if you have all those files in a common folder, e.g. `/static`, then just map the filter on an `url-pattern` of `/static/*` so that you don't need to check the content type everytime and can just set the response headers directly.
BalusC