我一直在尝试刷新我对HTTP / 1.1缓存的理解 - 我发现每隔一段时间我就必须做一些事情,因为似乎有太多可能的组合可以让我的大脑可靠地记住。
我认为Expires
或max-age
缓存控制指令被浏览器用作提示,而非铁定律:如果缓存条目过时(早于其最大年龄),浏览器可以验证它。
一位同事和我有一点关于这一点,他强迫我阅读RFC,我觉得它有点苛刻,但证明他完全正确:如果我理解正确,客户不允许使用他们知道过时的缓存条目。
换句话说:如果文档指定max-age
缓存标头,并且没有其他指令(如must-validate
)影响缓存行为,并且该文档的缓存条目变得陈旧,则浏览器将始终重新验证它
这是完全清楚和合乎逻辑的,为了让这个论点得到休息,我开始通过让服务器提供带有以下标题的测试JavaScript文件来凭经验确认:
< HTTP/1.1 200 OK
< Content-Type: application/x-javascript; charset=UTF-8
< Cache-Control: public, max-age=30
< Date: Thu, 30 Jan 2014 22:11:28 GMT
< Accept-Ranges: bytes
< Server: testServer/1.0
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
此JavaScript文件包含在同一服务器上通过文档<script>
中的<head>
元素托管的HTML页面中。 HTML页面提供以下缓存控制标头:
Cache-Control: no-cache, must-revalidate, no-store, max-age=0
加载HTML页面后,我点击进入另一个页面,等待5分钟以获得良好的衡量标准,然后点击返回原始页面的链接,监控所有HTTP请求 - 并且从未请求过测试文件。这是与Firefox和Safari最新版本一致的再现。
这有点啰嗦,但我的问题的主旨是:我的测试似乎表明主流浏览器不尊重RFC,也不会重新验证过时的缓存条目。我误解了RFC吗?同样可能的是,我是否对我的测试进行了测试,有人可以证明他们错了吗?或者浏览器真的不尊重max-age
缓存指令吗?
答案 0 :(得分:1)
经过@CodeCaster的大量挖掘和帮助后,这个问题的典型答案是浏览器看起来似乎尊重RFC:过时的缓存条目总是被重新验证,除非是在直接或直接访问它们的特定情况下间接地,通过浏览器的历史。在这种情况下,RFC的13.3部分适用:
历史机制和缓存是不同的。特别是历史机制不应该试图显示资源当前状态的语义透明视图。相反,历史机制旨在准确显示用户在检索资源时看到的内容。
答案 1 :(得分:0)
我无法重现您的问题。我尝试使用ASP.NET MVC,使用以下代码:
public ActionResult Index()
{
Response.AddHeader("Cache-Control",
"no-cache, must-revalidate, no-store, max-age=0");
return View();
}
public ActionResult JavaScript()
{
Response.AddHeader("Cache-Control", "public, max-age=30");
return View();
}
public ActionResult Page2()
{
return View();
}
第一个操作返回索引页面(仅限相关标题):
HTTP/1.1 200 OK
Cache-Control: no-cache, no-store, must-revalidate, max-age=0
Pragma: no-cache
Expires: -1
Vary: Accept-Encoding
Content-Length: 182
<html>
<head>
<script src="/Home/JavaScript" type="text/javascript"></script>
</head>
<body>
<a href="/Home/Page2">Page 2</a>
</body>
</html>
JavaScript返回如下:
HTTP/1.1 200 OK
Cache-Control: public, max-age=30
Vary: Accept-Encoding
Content-Length: 24
document.write('Foo');
而Page2只包含一个返回Home的链接。
现在,当我使用Internet Explorer 11,Chrome 32或Firefox 26时,我看到以下行为:
/
时,请求索引文档以及JavaScript文件,并返回如上所示,并通过Fiddler验证。但是,当我在任何浏览器中在任何浏览器中单击“后退”按钮一段时间后(大于或小于30秒),索引文件始终是,但JS文件是从不在任何浏览器中再次请求。
需要刷新(F5)或通过再次单击“Page 2”然后再返回“Home”来导航和返回,以使浏览器在JS文件过期后执行新的请求。