防止304 / If-modified-since / HEAD请求的标头


31

内容缓存后,我应该发送什么标题以完全停止对服务器的所有请求?

我们有一个非常高延迟的服务器(Sigh,VMWare),因此即使向HEAD服务器发送请求也要花费40ms。

当前,这些是正在发送/接收的报头;

第一个要求

客户发送;

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Pragma: no-cache, no-cache, no-cache
Cache-Control: no-cache, no-cache, no-cache

服务器响应;

HTTP/1.1 200 OK
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:51:51 GMT
Content-Type: text/plain
Vary: Accept-Encoding
Last-Modified: Tue, 31 Jan 2012 10:45:11 GMT
Content-Length: 14
Expires: Thu, 31 Jan 2013 14:51:51 GMT
Cache-Control: max-age=31536000

因此它将在未来发送,Cache-Control并将Expires标头设置为365天。不幸的是,在第二次刷新时,它再次请求了带有If-Modified-Since标题的对象。

第二个请求

GET http://dugong:8080/Rvi24mYJkxFRGNzq73PPvgWGh1j/IMG_2071.jpg HTTP/1.1
Host: dugong:8080
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:9.0) Gecko/20100101 Firefox/9.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
If-Modified-Since: Tue, 31 Jan 2012 10:45:11 GMT
Cache-Control: max-age=0

响应;

HTTP/1.1 304 Not Modified
Server: nginx/1.0.11
Date: Wed, 01 Feb 2012 14:58:00 GMT
Vary: Accept-Encoding
Expires: Thu, 31 Jan 2013 14:58:00 GMT
Cache-Control: max-age=31536000

不幸的是,由于愚蠢的过时的代理软件,我们无法使用Keep-Alive,或将任何其他服务器/代理放在应用程序的前面。我们也无法提高服务器性能并减少网络延迟。我一直在尝试找出可以发送哪些标头以摆脱301请求。我试过使用ETags,但这没什么区别,它仍然发送If-modified-since标头。我也尝试过删除Last-Modified标头,但这只会导致没有缓存的标准GET请求(检查日志,服务器仍在接收请求)。

客户端是Firefox(主要是),IE 7、8和(某些)9,Chrome和Safari的混合体,但是此行为似乎在所有经过测试的浏览器中均出现。

TL; DR;

糟糕的网络,我应该发送哪些标头以告知客户端永远不要If-modified-since向服务器发送请求以验证其缓存,并保持内容被缓存直到Expires标头得到满足?

我可能缺少明显的东西,但是我尝试的一切似乎都能产生相同的结果。

我们的应用程序服务器前面有一个NGINX服务器,因此我可以随意添加/删除任何标头。我们的代理不支持Keep-Alive,也无法提高网络性能。由于糟糕的软件设计,Web应用程序在每个页面加载时加载+100资源(是的,企业软件很烂),每个对象的延迟约为40-50ms。


1
嗯,很奇怪。发送Expires和max age标头应防止进一步请求该图像。编辑:顺便说一下,将JPG发送为text/plain有何处理?
DisgruntledGoat 2012年

1
@DisgruntledGoat Ahh,您已经假设.jpg文件实际上是图像而不是文本文档。欢迎来到我的世界=)(实际上是一个文本文件,其中包含用于测试的“ Hello World”,该软件会按顺序将所有文件重命名为IMG_xxxx.jpg,而不管类型如何。很酷吧?)
涂抹

您使用什么来设置http请求标头?
barlop

Answers:


25

您无法真正控制用户代理决定发送给您的标头。如果有问题的文件在浏览器的缓存中,并且确定需要检查新版本,则它将进行检查。根据本文的介绍,以下是浏览器要求使用If-Modified-Since的情况:

  • 缓存的条目没有到期日期,并且在浏览器会话中第一次访问内容
  • 缓存的条目具有到期日期,但已到期
  • 用户已通过单击刷新按钮或按F5来请求页面更新

因此,如果您要重新加载页面以测试缓存,则该页面将无法工作,因为浏览器将重新请求图像。尝试单击一个链接,然后单击另一个链接返回首页。如果您的用户定期重新加载页面,则可能需要重新考虑您的站点/应用程序结构以防止这种情况。

可能有帮助的一件事是在缓存控制标头(即)中添加“ public” Cache-Control: public, max-age=31536000最近我还了解到,有效期超过一年是无效的。由于您的有效期限恰好是一年,因此可以将其缩短几天或几周,以确保该文件保留在浏览器缓存中并且不会被丢弃。


有趣的是,我将到期时间降低到60天,并添加公共标志,然后看看会发生什么。这似乎是在链接单击而不是F5上发生的(根据Firebug和服务器日志)
涂抹

从技术上讲,HTTP / 1.1规范仅表示“服务器不应在未来一年内发送Expires日期”(大概是因为这要在到期前花费很长的时间),而将来的“大约一年”才是适当的到期时间需要发送永不过期的内容的时间。
Ilmari Karonen '02

1
经过一番摸索后,我得出结论说365d的有效期不会影响我们的客户,但是为了安全起见,我已将其丢弃,这似乎Cache-Control: public,...是解决此特定情况的关键。
涂抹

您是说“公共”标头修复了不必要的往返吗?我尝试过,但是没有成功……
phtrivier 2013年

2
如果我的答案不清楚,请在浏览器中重新加载页面,然后再次请求文件。只需单击链接即可打开页面,浏览器将使用其缓存。
DisgruntledGoat 2013年


3

我遇到了同样的问题,并且请求肯定在服务器上响应它的304状态-我正在通过某些C#发送304,并确保它在服务器上起作用。

我只Cache-Control: private定了。不max-age,不,Expires它按预期运行;将服务器与If-Modified-Since我期望的值进行比较,然后将其与期望值进行比较,并提供304空响应主体-否则200,将响应主体填满。

在客户端上设置Expires标头具有所需的结果,并且200 - (from cache)没有HTTP请求到达服务器。

但是..我发现设置BOTH max-age=Expires会导致浏览器不发送If-Modified-Since标头并且如果值不匹配则根本不缓存。

需要注意的事情,如果您有缓存问题,并且组合使用了不同的标头。


1

有点偏离主题,但可能会有所帮助。您对缓存内容的请求的另一项改进是在sessionStorage中进行缓存,这样您就无需让服务器验证缓存并接收304。例如,使用google,打开控制台并编写sessionStorage。您将看到它们正在使用sessionStorage缓存CSS或DOM。ofc,您不能在旧的IE浏览器中使用它。


0

查看您的源代码,并确保没有META REFRESH可以过渡到另一页。请改用sendRedirect之类的东西。在我的设置中,META REFRESH在IE中生成304,但在Chrome中不生成。sendRedirect在任何一个浏览器上均不会产生此错误。

<meta http-equiv="refresh" content="0;URL='nextpage'" />    

<% response.sendRedirect("nextpage") %>
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.