Safari没有发送“If-Modified-Since”和“If-None-Match”头信息。

14

我正在使用PHP生成动态内容。

我发送以下HTTP头:

HTTP/1.1 304 Not Modified
Date: Sun, 09 Dec 2012 17:24:41 GMT
Server: Apache
Connection: keep-alive, Keep-Alive
Keep-Alive: timeout=1, max=100
Etag: "237f43b800e655dbe6567f7d32d34c99"
Expires: Sun, 16 Dec 2012 17:24:41 GMT
Cache-Control: max-age=604800
Vary: Accept-Encoding

我随后检查Etag,如果匹配,则发送header('HTTP/1.1 304 Not Modified')。 这在Chrome和Firefox中完美执行。 然而,Safari(版本6.0.2)不发送“If-Modified-Since”和“If-None-Match”标头。 这是Safari在第二个页面访问时发送的请求标头:

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Cache-Control: max-age=0

该页面链接的所有其他文件都接收了正确的 Request-Headers,Safari 使用缓存文件或适当使用 304。

为什么 Safari 没有发送正确的 Request-Header? 我应该改变什么?

谢谢!


3
这些导航栏中列出的是所请求的实际页面的标题,还是像页面内资源一样链接到其他页面?似乎 Safari 不会在导航栏中请求的页面上检查页面缓存,但是如果它是另一个页面中的资源(ajax、js、css、img),它会首先检查缓存。 - Wing Lian
类似问题:https://dev59.com/EFbTa4cB1Zd3GeqP7hYo - ggkmath
3
这个问题已经太久了,无法验证,但您是否确实在使用“304未修改”响应发送这些标头,还是只是复制并粘贴错误,并且您正在使用“200 OK”发送这些标头? - akirk
@akirk - 我现在无法再检查了。但我记得已经尝试过Chrome和Firefox(如所述),它们都运行良好。 - basbebe
@Cleric 第一个帖子已经两年了 - 那时日期比现在晚七天。 - basbebe
显示剩余4条评论
3个回答

4

If-Modified-Since

If-Modified-Since的注释警告不要使用与Last-Modified响应头内容不同的东西:

注意:如果客户端在If-Modified-Since头中使用任意日期而不是从相同请求的Last-Modified头中获取的日期,则客户端应该意识到这个日期是根据服务器对时间的理解进行解释的。

您的响应没有包含Last-Modified,但即使有,规范中也没有说用户代理必须或应该发送If-Modified-Since,只是可以发送。

If-None-Match

关于为什么Safari不发送If-None-Match,我也不知道;你的ETag看起来是有效的。

一般情况下如何强制缓存

同样在一般情况下,规范中没有说你必须缓存,只是当你这样做时,你必须遵守Cache-Control。因此,这是一种有点不对称的关系,你可以强制(透明)缓存重新检查源服务器,但作为源服务器,你不能强制用户代理缓存。

我该怎么办?

Safari只是部分自由软件。所以,如果添加Last-Modified不起作用,就没有太多事情可以做了。


1
我遇到了与If-Modified-Since标头相关的相同问题,并且在最初返回Last-Modified标头但同时也返回具有相同值的Expires标头后,能够让Safari提供它。更多信息,请参见我在此相关问题上发布的解决方案,https://dev59.com/EFbTa4cB1Zd3GeqP7hYo#26511701 - LeastOne

1

我最终通过查找各大网站发送的标头(headers)来解决这个问题,最终得到了以下结果:

Last-Modified: {some date}
Cache-Control: max-age=0, must-revalidate
Expires: -1

这在我的Safari上可以工作。


1
这在2020年是有效的,可以强制Safari正确返回HTTP 304。 - Matt Komarnicki
1
我无法使其在初始页面加载时起作用(详见另一个答案)。 - Joe
这很奇怪 @J - NealeU

1

Safari 16.3(2023年3月)不会在浏览器发起的初始文档GET请求中发送If-Modified-Since或If-None-Match。

比较使用ETags和Last-Modified的example.com在Safari和Chrome之间的请求和响应头。

Safari

当重新加载example.com时,Safari不会发送If-Modified-Since或If-None-Matches头。

由于Safari不在请求中包含缓存信息,因此服务器必须返回HTTP代码200以及所有内容。

Safari network request

Chrome

当重新加载 example.com(不要过快地重新加载--Chrome 将快速重新加载解释为强制重新加载)时,Chrome 会发送 If-Modified-Since 和 If-None-Match 标头,这些标头由第一次加载 ETag 和 Last-Modified 标头填充。

由于 ETag 没有更改,服务器返回 HTTP 代码 304。 Chrome 网络请求


这很奇怪@Joe(不幸的是并不令人惊讶)。这是一个记录下来的更改吗? 我没有Mac可以使用,但我想知道是否启用devtools时出现了奇怪的行为? 如果我问了显而易见的问题,请原谅,但有时这些事情会发生。 - NealeU
我已经为开发工具启用了缓存,并且能够在没有开启开发工具的情况下观察到行为。我找不到错误报告。有很多关于Safari行为的参考资料 - 看起来这种行为至少存在自Safari 12以来:https://gertjans.home.xs4all.nl/javascript/cache-control.html - Joe
谢谢。令人惊讶的是任何东西都能工作! - NealeU

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接