Ruby on Rails, how to disable/turn off ETag

2019-04-24 08:49发布

问题:

Greetings,

How do I turn off ETag(s) in Ruby on Rails v2.3.5

When I do a direct request to to the RoR/Mongrel an ETag header is present.

TIA,

-daniel

回答1:

much easier:

config.middleware.delete Rack::ETag


回答2:

Putting response.etag = nil in a before_filter does not work. The etag is generated just before the response is send (it's caluculated from the body so after all rendering has been done).

The proper workaround to disable etag use and generation (and so save the time spend in md5) it this monkey patch:

module ActionController
  class Request
    # never match any incomming etag
    def etag_matches?(etag)
      false
    end
  end

  class Response
    # fake rails that our response already has an etag set and so none is generated automatically
    def etag?
      true
    end
  end
end


回答3:

There's an etag setter method on the ActionController::Response object, which deletes the ETag HTTP header if it's blank, so you should just be able to clear it in your controller (probably in a before filter):

response.etag = nil


回答4:

I don't think they are on by default.

My understanding is that they need to be explicitly set using stale?/fresh_when call or similar.



回答5:

I am working in Rails 4 on WEBrick, trying to get a response to cache until it expires at a specific time each day. It looks like the auto-generated ETag is interfering with the expiration cache which is why I searched for this answer. I didn't find anything helpful here, but I did solve my problem, so I'll share.

tl;dr Set the Last-Modified header

But set it to what? In my situation I was trying to optimize a web service that returned the results of a process that runs at the same time every day. My response headers ended up looking like this:

response.headers['Cache-Control'] = "max-age=86400"
response.headers['Expires'] = getCacheTime
response.headers['Last-Modified'] = getLastModified

First you want to explicitly write the Cache-Control header to overwrite whatever the default is. I set mine to be 24 hours to coincide with the maximum of my expiration header. I set the expiration header with a function the looks something like this:

def getCacheTime
    now = Time.now.utc
    cacheTime = Time.utc(now.year, now.month, now.day, 22, 00, 00)
    if now > cacheTime
        cacheTime = cacheTime + (60 * 60 * 24)
    end

    cacheTime.httpdate
end

The getLastModified function returns exactly 24 hours less than the getCacheTime function. It seems that setting this will suppress the ETag (another validation caching header) at least in my current development environment.



回答6:

Why not add a before_filter in your application controller which sets etag to nil?