问题
I have an action which I cache using
caches_action :my_action, :expires_in=>1.hours
and also set the expires headers in the action itself using
def my_action
...
expires_in 1.hours
send_data(...,:disposition => 'inline',:type => 'image/png',:filename => params[:title]+".png")
end
However, when I look at the cache control response header from a result that is coming as the result of a memcached hit, I get this:
Cache-Control: private, max-age=0, must-revalidate
The first time round, i.e. when there is nothing in the cache, it is what I expect, i.e.:
Cache-Control: max-age=3600, private
It looks like rails+memcached is neither caching the original response headers, nor setting appropriate headers itself. The result is that the client makes a request to the server each time even when the result (an image) hasn't changed. Though the action completes quickly as it gets a hit in the cache, it still winds up sending all the data again, which I'd like to avoid.
How do I get the headers to do the right thing so that the client either makes no request in the first place, or gets a 'not modified' response?
回答1:
I had the very same problem a few days ago. Debugging it seems that rails is not taking into acount the expires_in for caches_action.
What I found that works is to put the same inside a cache_path. For example insted of doing
caches_action :monthly_sales_by_category, :expires_in => 10.minutes, :cache_path => proc { |c|
category = c.params[:category]
{:cat => category}
}
what I did was the following
caches_action :monthly_sales_by_category, :cache_path => proc { |c|
expires_in 10.minutes, :public => false
category = c.params[:category]
{:cat => category}
}
And works like a charm. :)
回答2:
Make sure your environment is configured to support caching. So in config/environments/development.rb (or where ever) you should see:
config.action_controller.perform_caching = true
Also, the private cache tag tells intermediate cache servers not to store the content. This is secure by default. If you want to change this behaviour, just set your cache like this:
expires_in(1.hours, :private => false, :public => true)
In order to skip expensive processing on the server if the content has not changed, use:
if stale?(:etag => @model, :last_modified => @model.updated_at.utc)
# Expensive stuff in here.
respond_to do |format|
...
end
end
来源:https://stackoverflow.com/questions/1251992/how-to-get-caches-action-to-set-expires-headers-when-there-is-a-hit-in-memcached