![Apache 不会为静态文件提供 304 Not Modified 响应](https://linux22.com/image/756761/Apache%20%E4%B8%8D%E4%BC%9A%E4%B8%BA%E9%9D%99%E6%80%81%E6%96%87%E4%BB%B6%E6%8F%90%E4%BE%9B%20304%20Not%20Modified%20%E5%93%8D%E5%BA%94.png)
我正在运行一个 Apache Web 服务器,从文件系统提供大型静态图像。我已将服务器配置为返回有效的缓存标头,如下所示:Header merge Cache-Control "public, max-age=31536000, immutable"
这一切都很好,但是当用户在浏览器中重新加载图像时,Apache 永远不会返回响应304 Not Modified
。
我运行了这个 curl 命令(出于保密原因,我更改了主机名):
curl -o /tmp/image.png -v -u test:example http://blah.example.com/static/images/covers/436g2gu94kxin4x7
这是来自 curl 的请求标头。
GET /static/images/covers/436g2gu94kxin4x7 HTTP/1.1
Host: blah.example.com
Authorization: Basic dGVzdDpleGFtcGxl
User-Agent: curl/7.64.1
Accept: */*
If-Modified-Since: Thu, 30 Apr 2020 02:21:47 GMT
我期望得到 304 响应,但是我得到的却是:
HTTP/1.1 200 OK
Date: Fri, 28 Aug 2020 04:59:54 GMT
Server: Apache/2.4.25 (Debian)
Content-Type: image/png
Content-Length: 3115720
Last-Modified: Thu, 30 Apr 2020 02:21:47 GMT
Vary: Accept-Encoding
Cache-Control: public, max-age=31536000, immutable
我读过Apache 缓存指南,但这些似乎都与这种情况无关……这都是关于配置 Apache 自己的缓存(无论是在内存中还是在磁盘上),特别是为了支持 Apache 作为原始服务器的反向代理的情况。
但在这种情况下,文件已经位于本地磁盘上。没有原始服务器。我不希望/不需要 Apache 存储文件的单独“缓存”副本;我只希望 Apache 注意到Last-Modified
磁盘上文件的日期与日期匹配If-Modified-Since
,并在这种情况下返回304 Not Modified
。
我该如何设置?我是否必须让 Apache 存储其自己的单独缓存文件副本才能启用条件 GET?(那将是一个非常大的缓存,可能存储在磁盘上,这完全是一种浪费。)
答案1
第一,它真的没有缓存吗?
您的问题可能是 curl。我在一个我知道会返回 304 的 URL 上测试了您的代码,但使用上面的代码,它总是返回 200。您尝试过 Web 浏览器的开发人员工具吗?只要未选中“禁用缓存”,您就应该能够刷新 URL 并在第二次刷新时看到它返回 304。
其次,这可能是 Apache 的一个错误
我在您的结果中没有看到 ETag 标头。假设 Apache 确实没有添加它,那么您可能可以忽略它。但您仍然可以尝试将其添加到您的 Apache 设置中,以防万一:
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
(请确保使用 启用 headers mod a2enmod headers
。)
或者,更好的是,如果您使用的是 Apache 2.4.42 及更高版本 ( apache2 -v
),您可以在设置中尝试以下操作:
<IfModule mod_deflate.c>
DeflateAlterETag NoChange
</IfModule>
此问题是由 deflate 模块在 ETag 末尾添加压缩方法引起的。这导致 Apache 忽略缓存并始终返回 200。用他们自己的话说,这:
...阻止对压缩内容的条件请求提供“HTTP 未修改”(304)响应。
因此禁用该功能可以解决一些缓存问题。