Apache 不会为静态文件提供 304 Not Modified 响应

Apache 不会为静态文件提供 304 Not Modified 响应

我正在运行一个 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)响应。

Apache 模块 mod_deflate

因此禁用该功能可以解决一些缓存问题。

相关内容