如何防止在Rails中缓存浏览器页面


151

Ubuntu-> Apache-> Phusion Passenger-> Rails 2.3

我网站的主要部分是对您的点击做出反应。因此,如果您单击链接,它将带您到目的地,并立即重新生成页面。

但是,如果您单击“后退”按钮,则看不到新页面。不幸的是,如果没有手动刷新,它不会显示。看来浏览器正在缓存它。我想确保浏览器没有缓存页面。

另外,我确实想为所有静态资产设置远期到期日期。

解决此问题的最佳方法是什么?我应该在Rails中解决这个问题吗?阿帕奇?Javascript?

谢谢您的帮助,杰森


唉。这些建议都没有强迫我寻找行为。

也许有一个JavaScript答案?我可以让Rails在注释中写出时间戳记,然后让javascript检查一下时间是否在五秒钟之内(或任何可行的方法)。如果是,那么很好,但是如果否,那么重新加载页面吗?

您认为这行得通吗?

感谢你的帮助,

杰森

Answers:


335

最后想通了这一点- http://blog.serendeputy.com/posts/how-to-prevent-browsers-from-caching-a-page-in-rails/application_controller.rb

在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和更低版本:

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

3
是否应该将其包装在“ if request.xhr”中?因此,仅在刷新Ajax时设置它,而普通页面则没有?
MintDeparture

3
Cache-Control: no-store只要浏览器符合HTTP 1.1,您才真正需要。第14.9.2节缓存可以存储的内容
gaqzi 2014年

28
1990年1月1日,是星期一!
2014年

2
它对我不起作用,我在application_controller.rb中添加了相同的代码,注销后我可以通过“后退”按钮查看最后一页。请指导我哪里错了?
索林2015年

1
这也不会在Rails应用程序中缓存JS和CSS吗?是否将为每个请求从服务器加载JS和CSS?
furiabhavesh 2015年


3

我已经在控制器中成功使用了这一行。它可以在Safari和Internet Explorer中使用,但是我还没有看到它可以在Firefox中使用。

response.headers["Expires"] = "#{1.year.ago}"

第二点,如果您使用rails helper方法,例如

stylesheet_link_tag

并将默认设置保留在您的网络服务器上,通常可以很好地缓存资产。


3
1.year.ago是不必要的开销。只需选择过去的任意时间,例如Fri, 01 Jan 1990 00:00:00 GMT
Archonic

6
@Archonic 1990年1月1日是星期一!
Thomas R. Koll '18

1

较干净的方法是编写一个Rack中间件,该中间件根据某些逻辑(例如,仅针对application / xml mime-type)更改Cache-Control标头。或者,对于一种较丑陋但仍有效的方法,可以将ActionDispatch :: Response :: DEFAULT_CACHE_CONTROL常量更改为“无缓存”。当然,如果需要控制器和/或操作粒度,则最好在控制器中执行。


1

注意事项:您不能有条件地清除缓存(就像before_filter只有reset_cache在用户已经在那儿时才调用)。您需要无条件清除缓存,因为浏览器不会发出新的请求,只是想看看这次是否需要重新加载,即使它不需要最后一次。

例:

before_filter :reset_cache, if: :user_completed_demographics?

由于浏览器使用“后退”按钮上的原始缓存标题,因此无法阻止用户访问之后再返回。

before_filter :reset_cache

但是将起作用(显然,在刷新页面并从添加之前清除缓存之后),因为在第一个请求下,浏览器将获得no-cache, no-store, ...并将其应用于将来的页面加载。


0

no_cache_control 宝石。

如果您需要对所有响应执行此操作(例如,通过渗透测试(BURP,Defectify等),则可以在Rails 4+上安装此Gem,以便为所有响应添加以下标头:

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: -1

就像魅力一样,它确实是正确的方法,可用于需要身份验证才能执行任何操作的安全HTTPS Web应用程序。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.