我正在尝试在浏览器中缓存(javascript)资源,并在响应标头中正确设置了所有Cache-control:max-age,Expires和Etag(如屏幕截图所示)。
浏览器请求“if-none-match”和“if-modified-since”,并且在这两种情况下满足条件:
所以我应该得到回复304,对吧?但不,我一直得到200 OK,这意味着apache每次都会继续为文件服务(尽管是压缩的)。经过Firefox,Chrome,curl测试 - 没用。服务器总是为整个文件服务,即使我没有要求它......
使用curl,我已将问题追溯到 gzip& ETAG :
以下是请求/回复:
请求标头00:09:12.000
响应标头Δ1100ms
答案 0 :(得分:10)
Apache mod_deflate
正在为每个实体创建唯一的Etag
URL的特定实体变体。每个协商的变体都需要有独特的ETag:s。对于mod_deflate
,就像将编码添加到已经计算的ETag一样简单。
一种解决方法是从Etag中删除编码:
<Location /js>
RequestHeader edit "If-None-Match" "^(.*)-gzip$" "$1"
Header edit "ETag" "^(.*[^g][^z][^i][^p])$" "$1-gzip"
</Location>
如果您将Apache 2.5与mod_deflate
模块一起使用,则可以使用指令DeflateAlterETag
来指定在压缩响应时如何更改ETag hader。
DeflateAlterETag AddSuffix|NoChange|Remove
来源:https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag
此blog post建议完全删除Etags并依赖Cache-Control
标题。
在httpd.conf
中执行此操作:
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
请注意,如果实体gzip:ed mod_deflate
仍然带有与普通entiy相同的ETag,这可能会导致ETag感知代理缓存不一致。
更多信息:
答案 1 :(得分:1)
gzip资源似乎也存在问题,例如.js .css和Vary:使用Chrome接受编码标头。
请检查我的Anwser:https://stackoverflow.com/a/40726246/135785
这解决了我的问题:
<FilesMatch "(\.js\.gz|\.css\.gz)$">
# Serve correct encoding type.
Header set Content-Encoding gzip
# Force proxies to cache gzipped & non-gzipped css/js files separately.
BrowserMatch "Chrome" ChromeFound
Header append Vary Accept-Encoding env=!ChromeFound
</FilesMatch>
检查您的Apache配置“Header附加Vary Accept-Encoding”
答案 2 :(得分:1)
一种尚未报告的解决方法是,您可以应用以下配置:
RequestHeader edit "If-None-Match" '^"((.*)-gzip)"$' '"$1", "$2"'
(最初由Joost Dekeijzer建议,请参见https://bz.apache.org/bugzilla/show_bug.cgi?id=45023#c22,并且现在仍在2.4版上运行)
答案 3 :(得分:0)
我强烈怀疑Cache-Control: max-age=0
有问题。
引用这篇文章及其出色的答案:What's the difference between Cache-Control: max-age=0 and no-cache?
另一方面,使用Cache-Control发送请求:no-cache(也称为“端到端重新加载”)不会重新验证,并且服务器在响应时不得使用缓存副本。