为什么当 Last-modified 与 If-modified-since 匹配时 Apache 会发送 200 OK?

为什么当 Last-modified 与 If-modified-since 匹配时 Apache 会发送 200 OK?

我正在尝试制定有关缓存策略的基本行为:文件应被缓存,并且每次都与服务器重新验证。所以我希望 Apache 返回 304。

这是每次浏览器刷新时出现的对话框:

Status Code:200 OK

Request Headers

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Cookie: ...
Host:...
If-Modified-Since:Tue, 14 Oct 2014 15:10:37 GMT
If-None-Match:"1461-505636af08fcd-gzip"
User-Agent:Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.116 Safari/537.36

Response Headers

Accept-Ranges:bytes
Cache-Control:No-cache
Connection:Keep-Alive
Content-Encoding:gzip
Content-Length:1412
Content-Type:text/html
Date:Tue, 14 Oct 2014 16:58:05 GMT
ETag:"1461-505636af08fcd-gzip"
Keep-Alive:timeout=5, max=99
Last-Modified:Tue, 14 Oct 2014 15:10:37 GMT
Server:Apache/2.4.6 (Ubuntu)
Vary:Accept-Encoding

(这是来自 chrome devtools,未选中“禁用缓存”)

您可以看到响应包含 Cache-Control:No-cache 标头,并且 If-modified-since 标头与 Last-modified 匹配。ETag 也匹配。

在这种情况下 Apache 不应该发送 304 吗?

编辑

使用以下命令禁用 Apache 中的 ETag

 Header  unset ETag

使得缓存行为更加可预测......

答案1

这似乎是一个老漏洞,解释为什么Header unset ETag会有区别。

Apache 2.4.0+ 会自动将压缩方法名称附加到 ETag(如在您的标题中所见),并阻止 304 响应。

最新版本的 mod_deflate 支持DeflateAlterETag可以用来控制这种行为:

DeflateAlterETag NoChange

答案2

这个请求显得有点奇怪:

Cache-Control:max-age=0

但可能更重要的是,我注意到返回的内容是 html。它是动态生成的吗?Apache 可能会发送 304 响应,但除非您提供静态内容,否则 Apache 的工作不是进行该调用,这取决于您的应用程序逻辑。例如,大多数 php 应用程序对此类内容的支持有限。

前端缓存可能会有所帮助,因为缓存应用程序可以检查修改时间、etag 等,但前提是应用程序和请求标头都支持缓存。例如,应用程序必须设置适当的标头来指示内容可缓存,而请求中的 Cache-control 标头之类的内容将否定缓存。您的标头看起来不支持缓存。

答案3

旧错误在最近的 Apache 版本中得到解决。

如果您无法使用 DeflateAlterETag,只需安装 brotli 压缩并使用 BrotliAlterEtag NoChange

答案4

如果您使用 配置了 Apache ,Apache 将永远不会向客户端Cache-Control:No-cache发送。HTTP 304 Not modified

如果您想重新验证某些请求,请Cache-Control:No-cache仅在需要的页面上放置。您不需要重新验证所有资源,这样做会浪费带宽。

相关内容