Skip to content
JakeHoward edited this page Jul 16, 2015 · 1 revision

Etag use cases

Etags can be used to enable conditional requests. Conditional requests come in two flavours:

  • conditional requests for validating cached representations (for GET requests)
  • conditional requests for concurrency control (for PUT, POST, DELETE requests) In this section we'll only focus on the first type of conditional requests as concurrency control is application domain specific and can't be handled in a generic way by a web library.

How Etags work

Let's take a look at an example of how Etags work for GET requests.

First client issues the following request:

GET /test HTTP/1.1
Host: www.utterlyidle.com

Server responds with:

HTTP/1.1 200 OK
Etag: "900150983cd24fb0d6963f7d28e17f72"
Content-Type: text/plain
Content-Length: 3

abc

Etag contains MD5 sum hex of the data returned in the response body. The next time client requests the resource representation it adds If-Non-Match header with the previously retrieved Etag value:

GET /test HTTP/1.1
Host: www.utterlyidle.com
If-None-Match: "900150983cd24fb0d6963f7d28e17f72"

After processing the request, server recomputes ETag and since it hasn't changed it sends 304 Not Modified response.

HTTP/1.1 304 Not Modified

So as we can see, we can reduce bandwidth usage (304 response has no content) at the expense of extra CPU cycles and memory to compute Etag on the server side. Bandwidth usage savings in this contrived example are not huge as the content is very simple but if the content was large the savings would be more significant.

Enabling Etags in Utterlyidle

To enable Etag support for GET requests in Utterlyidle you can add com.googlecode.utterlyidle.modules.PerformanceModule to your web application. PerformanceModule adds not only Etag support, but also caching support. Etags can be used without caching but it usually makes sense to use them together.

If you don't want to use PerformanceModule, you can always decorate HttpHandler with EtagHandler yourself.

import com.googlecode.utterlyidle.HttpHandler;
import com.googlecode.yadic.Container;

public class MyEtagModule implements RequestScopedModule {
    @Override
    public Container addPerRequestObjects(Container container) throws Exception {
        return container.decorate(HttpHandler.class, EtagHandler.class);
    }
}

Content-MD5

Every time Utterlyidle adds Etag header to the response, it also adds Content-MD5 header. This header is a base64 encoded MD5 sum used to detect unintentional modification of the message. It is not immune to the message tampering attacks that replace the message body and the header.

Clone this wiki locally