[Restful-rails-general] Accept header and cache

Nicola Piccinini pic at superfluo.org
Sat Jul 8 01:21:39 EDT 2006


> No, RESTful Rails shouldn't be adding Accept to the Vary header
> on its own, since at no point does it look at the Accept header
> and send different content base on its value.
> 
> If it was handling content negotiation (or conneg for short)
> then it would add the header.  Conneg is the process of looking
> at the Accept header, and then rendering a different view to
> match the capabilities of the browser/user-agent.

ok, so I think that the MimeResponds is responsible for this.

This dirty hack:

module ActionController::MimeResponds::InstanceMethods
   alias :_or_respond_to :respond_to

   def respond_to(*types, &block)
     _or_respond_to(*types, &block)
     response.vary << 'Accept'
   end
end

adds the 'Accept' value in the Vary header whenever the respond_to 
method is used. Imho, this makes sense because actually the respond_to 
method looks at the Accept header.

>> 2. shouldn't the value of Etag header in the second response be  
>> different from the first one? Again the experiments show that this  
>> isn't the case.
> 
> 
> The ETag is currently generated based on the lock_version
> values of all the models that were used to render the view.
> 
> It should probably include other information, like the template
> path and timestamp.  Unfortunately at the point where you need
> to test the conditions you don't necessarily know which template
> is going to be used, or if one is going to be used at all.

exactly!

> I'm not entirely sure how to best solve this though, but if anyone
> has ideas I'm open to them.

I haven't a solution but I like to discuss here about a ugly workaround 
to better understand the problem.

1. another dirty hack:

class HTTP::Conditions
   def consider_for_etag
     @consider_for_etag ||= []
   end
end

2. in Conditions#test!:

etag_values = [].concat(consider_for_etag).concat(lock_versions)
response.etag = Digest::MD5.hexdigest(etag_values.join('|'))

instead of
response.etag = Digest::MD5.hexdigest(lock_versions.join('|'))

3. finally, in RESTful controllers, when appropriate:

resource :by_id do |r|
   conditions.consider_for_etag << 'what you want'
# ...

In the case of content type, this could be:
   conditions.consider_for_etag << request.headers['Accept']

In this way the resource's Etag is surely different if the content type 
is different.
Of course it's sub-optimal because it could be different also when the 
content type is the same ... . To make it optimal we should ask the 
Responders for the chosen template before it really uses it but this 
seems to me difficult.

Moreover this instruction can't be added to the respond_to method 
because the Conditions#test! method is called before it.

Any comment?

Thanks, best regards.
-- 
Nicola Piccinini -- http://superfluo.org


More information about the Restful-rails-general mailing list