Apache没有发送304响应(如果启用了mod_deflate和AddOutputFilterByType)

Sab*_*bya 26 apache http mod-deflate httpd.conf

我在Apache httpd.conf中添加了以下行: -

AddOutputFilterByType DEFLATE text/html text/css application/javascript application/x-javascript application/json
Run Code Online (Sandbox Code Playgroud)

我有一个包含脚本的html文件(test.html): -

<script type="text/javascript" src="/test.js"></script>
Run Code Online (Sandbox Code Playgroud)

问题是,每次加载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
Run Code Online (Sandbox Code Playgroud)

但我真的想保持ETag(我知道有一个inode披露问题).

p00*_*0ya 25

这是Apache中的已知错误.请参阅Apache bug#45023,以及Apache 304 etags和mod_deflate的摘要.

从svn重建将解决问题.决议是将"-gzip"附加到etag的更改恢复.但是,存在相关的HTTP合规性问题.

如果您无法重建Apache,则会在错误报告中提供建议的运行时配置解决方法:

 RequestHeader  edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
 Header  edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""
Run Code Online (Sandbox Code Playgroud)

  • 在Apache 2.4上,只有"200 OK"响应 - 这个解决方案实际上有效吗? (3认同)
  • 这仍然是一个问题,我无法在上面工作(在Apache 2.4.7中).然而,在经过一些挖掘之后,我还认为ETag在Apache中并不是那么有用.如果ETag是内容的散列,那么ETag将是最有用的,因此即使时间戳改变,它仍然可以用来决定内容是否没有.对于Apache,ETag是inode,大小和最后修改数据的组合(默认使用大小和最后修改的值).因此,由于它使用的是文件属性,而不是内容的哈希值,因此我决定将其关闭并使用Last-Modified. (3认同)
  • 这似乎仍然是一个问题?我正在使用Apache 2.4.10 (2认同)

小智 9

"我还认为,无论如何,ETag在Apache中都没用."

错误,
例如,您有一个修改日期设置为的文件'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中仍然存在,因此,我编写了一个比上面更好的代码来解决这个问题.逐行扩展:

    1)如果浏览器发送了一个'If-None-Match'请求,其结尾有'-gzip',请设置变量request_etag = gzip.
    2)编辑请求标头以去掉'-gzip'部分.
    3)编辑响应头以添加'-gzip'部分,但前提是浏览器最初发送'-gzip'请求或响应内容是gzip编码.


您可以使用负向前瞻或负向后观,正则表达式速度相同,Apache支持两者

\"(.+(?<!-gzip))\"       #using negative lookbehind
\"((?:.(?!-gzip\"))+)\"  #using negative lookahead
Run Code Online (Sandbox Code Playgroud)

测试用例:

    "2e2-5388f9f70c580-afeg"
    "2e2-5388f9f70c580-gzin"
    "2e2-5388f9f70c580-gzipd"
    "2e2-5388f9f70c580-gzip"
    "2e2-5388f9f70c580gzip"

将此代码复制粘贴到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'"
Run Code Online (Sandbox Code Playgroud)


我个人使用下面的代码,如果它是一个gzip响应,最初剥离'-gzip'部分,并且不重新加载它,所以浏览器永远不会发送'-gzip' 'If-None-Match'标题.

Header edit ETag "(.+)-gzip\"$" "$1\"" "expr=resp('Content-Encoding') == 'gzip'"
Run Code Online (Sandbox Code Playgroud)


pow*_*tac 0

也许您使用(squid)代理来操纵 HTTP 请求?