HTTP Cache Headers in Servlets

16

I would like to know if there are libraries or solutions to handle requests containing headers such as Last-Modified , If-Modified-Since , If-Range If-None-Match , etc. and produce replies with Cache-Control , ETags , Pragma , 304 , Expires , etc. in Servlets.

While I know that these cache and download control headers are more relevant to static resources, I ran into a situation (which I think is fairly common) where support for these headers increases performance and decreases application costs.

In my specific case, I'm building an open-source application to create collages on Facebook with a colleague (see link if relevant: link ). This app is hosted on GAE that imposes limits and charges for external requests .

In our case we coded a Servlet that acts as a Proxy and image resizer of Facebook (link: ProxyServlet ). The proxy is required to bypass security exceptions at the time of exporting Canvas content related to Politics of the same origin since the Facebook's static resource servers do not implement CORS headers.

In this proxy case we could simply delegate the headers of request from Servlet to Facebook:

public static final ImmutableSet<String> excludedHeaders = 
    ImmutableSet.of("Cookie", "Host");

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    final HttpURLConnection connection;
    try {
       // código para abrir o request
       final Enumeration<String> headerNames = request.getHeaderNames();
       while (headerNames.hasMoreElements()) {
           final String headerName = headerNames.nextElement();
           final String headerValue = request.getHeader(headerName);

           if (!excludedHeaders.contains(headerName)) {
               log.info(headerName + " : " + headerValue);
               connection.setRequestProperty(headerName, headerValue);
           }
       }
    }
    // Restante do código
}

And copy the headers and status code of the Facebook response back to the Servlet.

final int httpCode = connection.getResponseCode();
response.setStatus(httpCode);
for (Map.Entry<String, List<String>> entry : connection.getHeaderFields().entrySet()) {
    final String header = entry.getKey();
    log.info(entry.getKey() + " = " + entry.getValue());
    for (String headerValue : entry.getValue()) {
        response.addHeader(header, headerValue);
    }
}
// Código para tratar o corpo da resposta, e em caso de status 200, redimensioná-la.

This was enough to make the application more responsive and greatly alleviate the amount of external requests (repeated images are cached in the browser and requests consecutive do not hit the Servlet).

However, I do not consider this a complete or generic solution (since it is specific to proxy servlets).

In Stack Overflow in English I found references to FileServlet bo < BalusC , which implements the Servlet issue for local downloads quite a bit (its code treats all the headings mentioned "on the nail"). in addition to supporting GZIP compression ).

But I wondered if there is a more generic library or solution to address this type of problem (for example, using filters and / or a simplified API to abstract implementation details).

Has anyone heard of anything like this? (And if not, does anyone apply to start writing something like this?: D).

    
asked by anonymous 24.12.2013 / 19:34

1 answer

6

The Java EE Cache Filter library, which consists of a set of filters for manipulation of headers.

Because filters can be mapped via web.xml , I believe there should not be much difficulty in applying it.

The filter for adding the cache is CacheFilter . Here's an example use:

<filter>
    <filter-name>imagesCache</filter-name>
    <filter-class>com.samaxes.filter.CacheFilter</filter-class>
    <init-param>
        <param-name>static</param-name>
        <param-value>true</param-value>
    </init-param>
    <init-param>
        <param-name>expirationTime</param-name>
        <param-value>2592000</param-value>
    </init-param>
</filter>

<filter-mapping>
    <filter-name>imagesCache</filter-name>
    <url-pattern>/img/*</url-pattern>
</filter-mapping>

Note : I personally did not test with this library to find out the details of its operation. But I believe the solution using filters is appropriate.

On the other hand, depending on the volume of data, you may need to use a more specialized service such as Amazon S3 or CloudFlare . In this scenario, you feed the service with the images and it is responsible for resizing and distributing it quickly, efficiently and with configurable caching.

    
26.12.2013 / 12:17