Prev | Current Page 334 | Next

Brad Ediger

"Advanced Rails"


Often, the ETag is a hash of the response body, but it can be anything that is likely to
change when the body does. Another common method used for static content is to
use some combination of the file??™s inode number, last-modified time, and size; this is
very efficient because all of that information can be determined with a stat(2)
syscall. Of course, this method breaks down in clusters (where the static files might
span filesystems) or when serving dynamic content.
Rails has built-in support for transparently generating ETags. The method used is the
???simplest thing that could possibly work???; it is generic because it makes no assumptions
about the structure or semantics of an application. Its implementation is simple
enough that it can be shown here:
def handle_conditional_get!
if body.is_a?(String) &&
(headers['Status'] ? headers['Status'][0..2] == '200' : true) &&
!body.empty?
self.headers['ETag'] ||= %("#{Digest::MD5.hexdigest(body)}")
self.headers['Cache-Control'] = 'private, max-age=0, must-revalidate' if
headers['Cache-Control'] == DEFAULT_HEADERS['Cache-Control']
if request.headers['HTTP_IF_NONE_MATCH'] == headers['ETag']
self.headers['Status'] = '304 Not Modified'
self.body = ''
end
end
end
On each request with a 200 OK response, Rails generates an MD5 hash of the
response body and sets it as the ETag (unless one has already been set; this allows
you to provide custom ETags simply by setting them).


Pages:
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346