Finally figured this out - http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/ in application_controller.rb
After Rails 5:
class ApplicationController < ActionController::Base
before_action :set_cache_headers
private
def set_cache_headers
response.headers["Cache-Control"] = "no-cache, no-store"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT"
end
end
Rails 4 and older versions:
class ApplicationController < ActionController::Base
before_filter :set_cache_headers
private
def set_cache_headers
response.headers["Cache-Control"] = "no-cache, no-store"
response.headers["Pragma"] = "no-cache"
response.headers["Expires"] = "Mon, 01 Jan 1990 00:00:00 GMT"
end
end
use:
expires_now()
http://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-expires_now
I have used this line with some success in the controller. It works in Safari and Internet Explorer but I haven't seen it work with Firefox.
response.headers["Expires"] = "#{1.year.ago}"
For your second point, if you use the the rails helper methods like
stylesheet_link_tag
and leave the default settings on your webserver, the assets are typically cached pretty well.
The cleaner way would be to write a Rack middleware, which changes the Cache-Control header based on some logic (for example, only for application/xml mime-type). Or, for an uglier, but still working approach, one could change the ActionDispatch::Response::DEFAULT_CACHE_CONTROL constant to 'no-cache'. Of course, if the controller and/or action granularity is required, then it's better to do this in the controller.
Point of note: You can't conditionally clear the cache (like if a before_filter
only calls reset_cache
if the user's already been there). You need to unconditionally clear the cache, because the browser won't make a new request just to see if this time, it needs to reload, even though it didn't need to last time.
Example:
before_filter :reset_cache, if: :user_completed_demographics?
won't work to prevent users from coming back after they've been there, since the browser uses the original cache headers on the Back button.
before_filter :reset_cache
will work, however (after refreshing the page and clearing the cache from before you added this, obviously), since, on the first request, the browser will get the no-cache, no-store, ...
and apply it to future page loads.
no_cache_control
Gem.If you need to do this for all responses, e.g. to pass a penetration test (BURP, Detectify, etc.), you can install this Gem on Rails 4+ in order to add the following headers to all responses:
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: -1
Works like a charm and is really the right way to go for secure, HTTPS web applications that require authentication to do anything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With