This log covers HTTP ETags usage in Rails development. ETag is a key to determine content has changed.

The ETag or entity tag is part of HTTP, the protocol for the World Wide Web. It is one of several mechanisms that HTTP provides for web cache validation, which allows a client to make conditional requests. This allows caches to be more efficient, and saves bandwidth, as a web server does not need to send a full response if the content has not changed.1

Typical Usage

Server returns the response with ETag value in HTTP response header. The client cache the response content. When client make a request next time which send its saved ETag with the request in If-None-Match field. If the ETag match, the server send back a short response with HTTP 304 Not Modified status.

Before using refresh_when

Imgur

  • First Request
    1. Render body
    2. Create ETag (headers['Etag'] = Digest::MD5.hexdigest(body))
    3. Include response body and ETag in the response
    4. Client cache response
  • Second Request
    1. Render body
    2. Create ETag (automatically created using response body)
    3. Compare ETag
    4. Not include body in response if ETag match
    5. Client render response from cache

The entire body is required to process in order to generate the ETag which is not efficient.

After using refresh_when

class ItemsController < ApplicationController
  def show
    @item = Item.find(params[:id])
    fresh_when(@item)
  end
end

When there are multiple arguments (ETag computation do support multiple values),

class ItemsController < ApplicationController
  # Equivalent to `fresh_when([@item, current_user.id])` inside `show`
  etag { current_user.id }

  def show
    @item = Item.find(params[:id])
    fresh_when(@item)
  end
end

Using refresh_when make the ETag generating process much efficient.

  • First Request
    1. Render body
    2. Create ETag (headers['Etag'] = Digest::MD5.hexdigest(@item.cache_key))
    3. Include response body and ETag in the response
    4. Client cache response
  • Second Request
    1. Render body
    2. Create ETag (automatically created using cache_key)
    3. Compare ETag
    4. Not include body in response if ETag match
    5. Client render response from cache
  1. https://en.wikipedia.org/wiki/HTTP_ETag