Http 同时具有gzip和Etag时无法缓存资源
我试图在浏览器中缓存一个(javascript)资源,并在响应头中正确设置了所有缓存控制:max age、Expires和Etag(如屏幕截图所示) 浏览器请求“如果不匹配”和“如果修改自”,在这两种情况下都满足以下条件:Http 同时具有gzip和Etag时无法缓存资源,http,caching,header,response,Http,Caching,Header,Response,我试图在浏览器中缓存一个(javascript)资源,并在响应头中正确设置了所有缓存控制:max age、Expires和Etag(如屏幕截图所示) 浏览器请求“如果不匹配”和“如果修改自”,在这两种情况下都满足以下条件: 如果修改自=上次修改(文件从未更改) 如果none match=Etag(同样,文件从未更改) 所以我应该得到回应304,对吗?但是没有,我一直得到200 OK,这意味着apache每次都在提供文件(尽管是压缩的)。使用Firefox、Chrome、curl进行测试——没
- 如果修改自=上次修改(文件从未更改)
- 如果none match=Etag(同样,文件从未更改)
- 如果我删除gzip(并从请求Etag中删除后缀-gzip)——一切都很好:304
- 如果我保留gzip并删除请求Etag——一切都很好:304
- 但是,如果我同时保留'accept encoding:gzip'和Etag,即使请求和响应Etag是相同的(这次末尾是'-gzip',服务器返回错误的200。感觉就像apache在gzip失败之前比较了etag,确定它不匹配,然后提供gzip文件,即使在gzip之后etag匹配
- 请求方法:获取
- 状态代码:HTTP/1.1200正常
- 用户代理:Mozilla/5.0(X11;Ubuntu;Linux i686;rv:36.0) Gecko/20100101 Firefox/36.0
- 如果没有匹配:“24e55-51138062ce6c0-gzip”
- 如果修改自:2015年3月14日星期六04:26:43 GMT
- 连接:保持活力
- 缓存控制:最大年龄=0
- 接受语言:en-US,en;q=0.5
- 接受编码:gzip,deflate
- 接受:/
- 改变:接受编码
- 服务器:Apache/2.4.7(Ubuntu)
- 最后修改:2015年3月14日星期六04:26:43 GMT
- 保持活动状态:超时=5,最大=100
- 到期日期:2015年3月25日星期三格林尼治标准时间16:09:13
- Etag:“24e55-51138062ce6c0-gzip”
- 日期:2015年3月18日星期三格林尼治标准时间16:09:13
- 内容类型:应用程序/javascript
- 内容长度:53331
- 内容编码:gzip
- 连接:保持活力
- 缓存控制:最大年龄=604800
缓存控制:max age=0
有故障
引用这篇文章及其极好的答案:
另一方面,使用Cache-Control:no-Cache(又名“端到端重新加载”)发送请求不会重新验证,服务器在响应时不得使用缓存副本
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>
资料来源:
这建议完全删除ETag,并依赖缓存控制
头
要在httpd.conf
中执行此操作:
<IfModule mod_headers.c>
Header unset ETag
</IfModule>
FileETag None
标题未设置ETag
FileTag无
请注意,如果由mod_deflate
生成的实体gzip:ed仍然携带与普通实体相同的ETag,这可能会导致ETag感知代理缓存中的不一致性
更多信息请点击此处:
<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>
#提供正确的编码类型。
标题集内容编码gzip
#强制代理分别缓存gzip和非gzip css/js文件。
BrowserMatch“Chrome”ChromeFound
头附加变量接受编码环境=!镀铬
检查Apache配置中的“Header append Vary Accept Encoding”一个尚未报告的解决方法是,您可以应用此配置:
RequestHeader edit "If-None-Match" '^"((.*)-gzip)"$' '"$1", "$2"'
(最初由Joost Dekeijzer建议,请参阅,现在仍在使用版本2.4)感谢您的帮助,但不幸的是,问题并不是由于请求头中的max age=0。这是另一个请求,这次是对google托管的jquery库的请求,google在那里给了我正确的响应。不要将请求中的max age=0与响应中的max age=0混淆(这实际上意味着“重新验证”)。此外,问题不在于服务器端的缓存,而在于客户端(浏览器)端的缓存我指的是从客户端发送的头(请检查答案中的引号),而您的问题似乎在于服务器端的缓存,因为服务器不会向您返回304。不过,谷歌的例子很清楚。另一个选择是,您的URL中有参数-请参阅此处的列表:否,无参数。。。实际上,这是url:
上次修改
(不发送ETag
)能解决这个问题吗?我认为仅仅删除-gzip
后缀的问题在于未压缩的内容(在gzip之前)就是正在缓存的内容。对于第一个解决方案,我删除了标题编辑(正如mod_deflate已经添加的那样),并添加了RequestHeader edit“If None Match”“^(.*)-gzip\$”“$1\”
(注意末尾添加的双引号),因为ETag经常被引用。
RequestHeader edit "If-None-Match" '^"((.*)-gzip)"$' '"$1", "$2"'