How to get caches_action to set expires headers wh

2019-05-18 11:52发布

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?

2条回答
来,给爷笑一个
2楼-- · 2019-05-18 12:25

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. :)

查看更多
干净又极端
3楼-- · 2019-05-18 12:35

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
查看更多
登录 后发表回答