Question

For one controller (only), I'd like to use an ETag value generated outside of rails caching logic, and manage 304-vs-200 responses myself. It seems that nothing I do to set the ETag header works:

response.etag = myEtag
headers['ETag'] = myEtag
render :text => myText, :etag => myEtag

Rails always uses its own version.

I know I could disable caching app-wide, but I don't want that - just want to override it in the responses for one ActionController subclass.

Was it helpful?

Solution

fresh_when, etc. didn't quite suit my needs - in my case the solution was to refuse caching via

def caching_allowed?
  false
end

then set just the headers['ETag'] member on my response - setting any of the .etag options seems to cause Rails to MD5 All The Things.

OTHER TIPS

Also if you would like to overwrite it directly, you can set the etag value like below:

headers['ETag'] = 'xxxxxx'

Code reference from Rack (rack-1.6.11/lib/rack/etag.rb)

if etag_status?(status) && etag_body?(body) && !skip_caching?(headers)
    original_body = body
    digest, new_body = digest_body(body)
    body = Rack::BodyProxy.new(new_body) do
        original_body.close if original_body.respond_to?(:close)
    end
    headers[ETAG_STRING] = %(W/"#{digest}") if digest
end

private

def skip_caching?(headers)
    (headers[CACHE_CONTROL] && headers[CACHE_CONTROL].include?('no-cache')) ||
      headers.key?(ETAG_STRING) || headers.key?('Last-Modified')
end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top