我在Apache httpd.conf中添加了以下行: -
AddOutputFilterByType DEFLATE text/html text/css application/javascript application/x-javascript application/json
我有一个包含脚本的html文件(test.html): -
<script type="text/javascript" src="/test.js"></script>
问题是,每次加载test.html时,test.js也会加载HTTP状态:200。
问题是:为什么不满足条件GET?
如果我在httpd.conf中注释掉“AddOutputFilterByType”行,Apache就会发送304。
如果我在httpd.conf中启用AddOutputFilterByType,则请求标头为: -
Host: optimize User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US; rv:1.9.0.10) Gecko/2009042316 Firefox/3.0.10 GTB5 (.NET CLR 3.5.30729) FirePHP/0.2.4 Accept: */* Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip, deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://optimize/ Cookie: PHPSESSID=nbq6h0eeahkshkcbc6ctu2j2b4 If-Modified-Since: Tue, 19 May 2009 07:06:46 GMT If-None-Match: "2000000000717f-2c25a-46a3e8dcc2ad8"-gzip Cache-Control: max-age=0
响应头是: -
Date: Fri, 22 May 2009 07:03:40 GMT Server: Apache/2.2.9 (Win32) PHP/5.2.6 Last-Modified: Tue, 19 May 2009 07:06:46 GMT Etag: "2000000000717f-2c25a-46a3e8dcc2ad8"-gzip Accept-Ranges: bytes Vary: Accept-Encoding Content-Encoding: gzip Content-Length: 52583 Keep-Alive: timeout=5, max=98 Connection: Keep-Alive Content-Type: application/javascript
更新:我注意到,如果我禁用ETag,它可以正常工作。我的意思是它发送304。
FileETag None
但我真的想保留ETag(我知道有一个inode泄露问题)。
答案 0 :(得分:25)
这是Apache中的已知错误。请参阅Apache bug #45023和summary of Apache 304 etags and mod_deflate。
从svn重建将解决问题。决议是将“-gzip”附加到etag的更改恢复。但是,存在相关的HTTP合规性问题。
如果您无法重建Apache,则错误报告中会提供建议的运行时配置解决方法:
RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""
答案 1 :(得分:9)
&#34;我还认为ETag在Apache中并不是那么有用。&#34;
错误, 例如,您有一个修改日期设置为
'2016.07.27 05:00:00'
的文件,您将其上传到您的站点,浏览器使用HTTP代码200获取此文件,然后缓存它并每次使用HTTP 304重新验证。
接下来,您再次上传具有相同文件名的文件,但使用较早的时间戳'2013.07.27 05:00:00'
和其他内容。
如果在服务器上禁用ETag,浏览器将仅使用If-Modified-Since:
请求来确定服务器上的文件是否已更改,因此请求将为If-Modified-Since: 2016.07.27 05:00:00
,但文件不是在此日期之后修改,因此即使文件已更改,也会返回HTTP 304。
如果在服务器上启用了ETag,除If-Modified-Since:
之外,将有来自浏览器的If-None-Match:
标头将检测到该文件已更改(默认情况下 - 时间戳不匹配+大小不匹配),文件将被重载。
这个问题在Apache 2.4.23中仍然存在,因此,我已经编写了比上述更好的代码来解决这个问题。逐行扩展:
你可以使用负向前瞻或负面后瞻,正则表达速度是相同的,Apache支持两者
\"(.+(?<!-gzip))\" #using negative lookbehind
\"((?:.(?!-gzip\"))+)\" #using negative lookahead
测试用例:
复制 - 将此代码粘贴到Apache .conf
SetEnvIf If-None-Match "-gzip\"$" request_etag=gzip
RequestHeader edit If-None-Match "(.+)-gzip\"$" "$1\""
Header edit ETag "(.+(?<!-gzip))\"$" "$1-gzip\"" "expr=reqenv('request_etag') == 'gzip' || resp('Content-Encoding') == 'gzip'"
我个人使用以下代码,即剥离&#39; -gzip&#39;首先,如果它是一个gzip响应,并且没有重新加载,那么浏览器永远不会发送&#39; -gzip&#39;
'If-None-Match'
标题。
Header edit ETag "(.+)-gzip\"$" "$1\"" "expr=resp('Content-Encoding') == 'gzip'"
答案 2 :(得分:2)
我知道这是一个非常古老的问题,但它似乎是一个更新的答案。
要让Apache不附加-gzip
后缀,您必须使用DeflateAlterETag
指令,其值为NoChange
。
请参阅此处的文档:http://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag
答案 3 :(得分:0)
也许您使用操纵HTTP请求的(squid)代理?