Here is a relevant source code of Rack::ETag
:
def call(env)
status, headers, body = @app.call(env)
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'] = %("#{digest}") if digest
end
unless headers['Cache-Control']
if digest
headers['Cache-Control'] = @cache_control if @cache_control
else
headers['Cache-Control'] = @no_cache_control if @no_cache_control
end
end
[status, headers, body]
end
As you can see, digest is calculated based on response body (using digest_body
). Here's the source:
def digest_body(body)
parts = []
digest = nil
body.each do |part|
parts << part
(digest ||= Digest::MD5.new) << part unless part.empty?
end
[digest && digest.hexdigest, parts]
end
You can hook inside of that method. I believe you will find that there's something dynamic in your response and this blocks you from using ETag
header. For example, there maybe CSRF protection tokens in your forms, or something like that. I would strongly suggest you to use something like debugger or pry for placing breakpoints.