16
I would like to know if there are libraries or solutions to treat requests containing headers as Last-Modified
, If-Modified-Since
, If-Range
(for download summary), If-None-Match
, Cache-Control
, Pragma
, etc and produce code responses 304
, Etags, Expires
, Last-Modified
, Content-Range
, etc in Servlets.
While I know those headlines cache and download control are more relevant to static resources, I ran into a situation (which I think is quite common) in which the support for these headers increases the performance and reduces an application’s costs.
In my specific case, I’m building an application open-source for creating collages on Facebook with a colleague (follow link if relevant: http://sfcb.7rtc.com). This application is hosted on GAE that imposes limits and charges for external requests.
In our case we encode a Servlet that acts as a Proxy and Facebook image resizer (link: Proxyservlet). The proxy is necessary to circumvent security exceptions when exporting Canvas content related to Policy of the same origin since Facebook’s static resource servers do not implement headers CORS.
In this case the proxy 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 Facebook response status code back to 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 requests external (repeated images are curled 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 Rvlets).
In the Stack Overflow in English I found references to Fileservlet bo Balusc that implements quite complete the issue of Servlets for local downloads (its code handles all the headers mentioned "in the nail", in addition to supporting gzip compression).
But I wondered if there is a more generic library or solution to treat this type of problem (for example, with the use of Filters and / or a simplified API to abstract implementation details).
Has anyone ever heard of such a thing? (And if not, does anyone apply to start writing such a thing? D).
Whenever I needed these headers, I did the work on the nail from the
HttpServletRequest
. As in practice the headers within it are only oneMap
very simple and each of these headers has simple values and pre-defined (with the exception of Etag which is a little bit more complicated), I think that no one took the trouble to worry about leaving things a little sweeter and more abstract for programmers.– Victor Stafusa
Revisiting the issue now, I have seen several different cases and problems related to headers, Cdns and caching. Perhaps due to the many varieties of applications, the specific use they make of the HTTP protocol and the limitations of the Cdns themselves, many people end up implementing customized solutions. For example, Amazon’s Cloud Front does not support GZIP compression on-the-fly of resources stored in S3. The solution is to use a proxy with Nginx to intercept requests.
– utluiz
Unfortunately, there are no (or unknown) canonical solutions for caching, especially in Java. So it would be difficult to think of a better generic solution than the one presented in the question. But it is a promising and important topic, with much to be explored, which needs innovation especially in a world where every millisecond is a concern.
– utluiz