-1

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.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • you can try "fresh" read more here http://stackoverflow.com/questions/832035/rails-etags-vs-page-caching-file-cache – Jakub Oboza May 14 '12 at 15:41

2 Answers2

0

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.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • Question, where do you put that method? – Hackeron Jul 06 '15 at 18:45
  • This was forever ago, but as I recall I was overriding the method in ActionController: http://api.rubyonrails.org/v3.2.0/classes/ActionController/Caching.html#method-i-caching_allowed-3F – Paul Roub Jul 06 '15 at 20:25
0

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
barbsan
  • 3,418
  • 11
  • 21
  • 28
  • Please notice that this is one of the methods mentioned in the original question, and as _part_ of the answer. What's new/different here? – Paul Roub Jul 03 '19 at 19:02