On Being for the Web
Tim Bray, talking about ETags:
What you want to do is compute the ETag based on the underlying data resources that actually drive the page creation; the input to that process, not its output. This is often going to be a small number (sometimes one) of timestamp or version fields in a database row, or metadata from the underlying filesystem. It’s also going to be application-dependent. So a framework that was really designed for the Web would expose the ETag generation to the application programmer in a way that let them be smart about conserving the resources that actually matter.
Very true; this is what Joe Gregorio wrote about a while ago. Contrary to the Tim’s impression, this seems to be exactly what Rails does:
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' 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
In other words: you can set the header yourself; if you do so, it’s set and Rails will leave it as is. Back in March, I thought that it might make sense to add something in the lower layers to support this. I’m not so sure anymore; it’s probably better to leave this to the application developer.
Um, are you sure? I’m reading that code and the first thing I see is
if body.is_a?(String) ...
which suggests that you’ve gone ahead and computed the whole result before you start thinking about conditional-get headers. My point is that the big win would be in avoiding computing the result body. But I’m still a relative Rails newb, so maybe I’m missing something obvious
First disclaimer: this is not my code, it’s taken straight from Edge Rails. What I meant is: the default code computes an ETag if it isn’t set. If you set the ETag yourself, no magic happens and it’s passed straight through.