浏览器不尊重 HTTP Expires 标头?

Posted

技术标签:

【中文标题】浏览器不尊重 HTTP Expires 标头?【英文标题】:HTTP Expires header not respected by browser? 【发布时间】:2010-11-05 17:52:01 【问题描述】:

我的(嵌入式)Web 服务器正在发送 Expires 标头,但浏览器似乎不尊重标头设置,即,如果我刷新页面,浏览器会请求应该缓存的资源.以下是正在交换的标头:

https://192.168.1.180/scgi-bin/ajax/ajax.cgi 获取 /scgi-bin/ajax/ajax.cgi HTTP/1.1 主机:192.168.1.180 用户代理:Mozilla/5.0(Windows;U;Windows NT 6.0;en-US;rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729) 接受:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 接受语言:en-us,en;q=0.5 接受编码:gzip,deflate 接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.7 保活:300 连接:保持活动 缓存控制:max-age=0 HTTP/1.x 200 正常 日期:格林威治标准时间 2009 年 6 月 24 日星期三 20:26:47 服务器:嵌入式 HTTP 服务器。 连接:关闭 内容类型:文本/html -------------------------------------------------- -------- https://192.168.1.180/scgi-bin/ajax/static.cgi?fn=images/logo.jpg&ts=20090624201057 GET /scgi-bin/ajax/static.cgi?fn=images/logo.jpg&ts=20090624201057 HTTP/1.1 主机:192.168.1.180 用户代理:Mozilla/5.0(Windows;U;Windows NT 6.0;en-US;rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11 (.NET CLR 3.5.30729) 接受:image/png,image/*;q=0.8,*/*;q=0.5 接受语言:en-us,en;q=0.5 接受编码:gzip,deflate 接受字符集:ISO-8859-1,utf-8;q=0.7,*;q=0.7 保活:300 连接:保持活动 推荐人:https://192.168.1.180/scgi-bin/ajax/ajax.cgi 缓存控制:max-age=0 HTTP/1.x 200 正常 日期:格林威治标准时间 2009 年 6 月 24 日星期三 20:26:47 服务器:嵌入式 HTTP 服务器。 连接:关闭 过期:格林威治标准时间 2011 年 6 月 1 日星期三 20:00:00 内容类型:图片/jpg -------------------------------------------------- --------

ajax.cgi 返回一个带有徽标图形的 html 页面(通过 static.cgi 脚本),我希望将其缓存,但浏览器在每次刷新时都要求提供徽标。

【问题讨论】:

我看到您正在使用 HTTPS。这可能是没有按照您的预期完成缓存的原因吗?您可以尝试仅使用 HTTP 的版本吗? 【参考方案1】:

如果您刷新页面,浏览器会忽略 Expires 标头。它总是通过联系 Web 服务器来检查缓存条目是否仍然有效。理想情况下,它将使用 If-Modified-Since 请求标头,以便如果缓存条目仍然有效,服务器可以返回“304 Not modified”。

您没有设置 Last-Modified 标头,因此浏览器必须对内容执行无条件 GET 以确保它是最新的。

这篇博文描述了一些设置 Expires 和 Last-Modified 的经验法则:

http://blog.httpwatch.com/2007/12/10/two-simple-rules-for-http-caching/

【讨论】:

"如果您刷新页面,浏览器会忽略 Expires 标头。"谢谢!我不知道这个。【参考方案2】:

您在浏览器中做什么?我看起来像您单击重新加载按钮,甚至单击 shift+Reload 之类的按钮。通常,浏览器不会发送Cache-Control: max-age=0 标头。这意味着浏览器已经丢弃了缓存的图像并想要再次获取它。

如果您只是导航到另一个页面然后又返回,浏览器应该尊重您的 Expires 标头。

此外,您可以在回复中添加Cache-control: public 标头。这允许代理和浏览器显式缓存图像。

【讨论】:

这似乎是正确的。浏览器(Firefox?)正在发送 max-age=0,这意味着它不想要任何早于 0 的响应,即它想要访问源 Web 服务器。这就是“刷新”的定义。离开您的页面,然后再次粘贴 URL,看看会发生什么。 确实,我正在重新加载页面,我希望浏览器重新加载 html 但不是所有缓存的资源。我认为您必须执行 shift-click(或 control-click?不记得)以强制浏览器使所有资源上的缓存无效。我猜我的理解有误? 我也不确定。我认为浏览器在带/不带 Shift 的 F5/Reload 按钮上表现不同。 @user128602 刷新会忽略收到的任何 Expire,但仍有机会在刷新时利用浏览器缓存功能,以确保您的服务器发送文件的修改时间。通常它会这样做,除非您从脚本生成内容(如图像)而不是直接从浏览器服务器下载。如果服务器发送修改时间,浏览器发出的下一个请求(包括重新加载)将向服务器发送“if-modified”。如果服务器以“未修改”响应,则不执行下载。 CTRL+Refresh 意味着在丢弃缓存旁边省略“if-modified”检查。【参考方案3】:

您的 https 证书中的任何错误都会导致浏览器不尊重您的标头。

在没有 https 的情况下尝试它,看看它是否适用于普通 http。

看到这个答案https://***.com/a/17716911

【讨论】:

【参考方案4】:

CGI 脚本看起来像它有一个时间戳参数...这不会改变,是吗?浏览器应该将每个唯一的 URL 视为缓存中的不同对象,因此如果每个请求都更新,它将与缓存的图像不匹配。

此外,Expires 字段并非完全采用 RFC 1123 格式,因为日期需要两位数。这可能是也可能不是问题,但需要检查。浏览器包含Cache-Control: max-age=0,这表明它认为其缓存可能已过期。

一旦服务器收到此验证请求,它就可以返回304 (Not Modified)200 (OK),就像它目前所做的那样。

【讨论】:

不,时间戳没有改变。感谢您提供有关过期日期格式的提示,我会仔细检查。

以上是关于浏览器不尊重 HTTP Expires 标头?的主要内容,如果未能解决你的问题,请参考以下文章

Http头介绍:Expires,Cache-Control,Last-Modified,ETag

为静态资源启用浏览器缓存

不同的浏览器如何处理没有 Expires Header 的静态内容的缓存?

expires_in max-age 缓存控制不起作用

301 和 301 http 重定向是不是可以使用 expires 标头进行缓存?

浏览器缓存之Expires Etag Last-Modified max-age详解