views:

249

answers:

1

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?

A: 

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
askegg
yes caching is set up and working OK - the problem is the second go around when there is a hit in the memcache, the headers don't get set. also on the second go around, the action wouldn't be invoked due to the hit in memcache so I guess the third code fragment won't have any effect.
frankodwyer
Oh I see. I had your problem round the wrong way. That *is* odd. Can you post the relevant fragments of the logs?
askegg
According to this post Rails might be assuming an HTML document, thus the key may not match your request. Just a thought.http://gilesbowkett.blogspot.com/2007/07/little-rails-image-caching-caveat.html
askegg
Might be something on those lines alright - I'll try putting a .png extension in there and see if it helps. The cache key should be OK as it is definitely serving stuff up from the cache - the logs seem to indicate that and anyway the response time is much quicker through the cache. But perhaps it is confused about the mime type.
frankodwyer
will try and dig out some logs later today when back at the server - they don't say a lot mind you, but they do show the request coming from cache (also the response time is very obviously slower when there is a cache miss, so it's easy to spot a hit vs a miss - it's a pretty expensive action).
frankodwyer