2009-05-22 49 views
22

我在Apache的httpd.conf中添加以下行: - 一个Apache不发送304响应(如果mod_deflate模块和AddOutputFilterByType启用)

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

的问题是:为什么条件得到我不满意?

如果我注释掉httpd.conf中的 “AddOutputFilterByType” 行,阿帕奇发送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披露问题)。

+1

你有没有找到一个解决办法? Apache 2.4似乎也在做同样的事情,总是发送200响应gzip'd内容 – virtualeyes 2013-01-14 17:40:12

+0

任何你想保留ETags的原因?如果你只是提供已经具有“Last-Modified”日期来重新验证的静态内容,那么获得它们就没有意义。当然,砍掉它们现在是最简单的RFC兼容解决方法。 – 2016-10-02 21:09:09

+0

ETags *是*需要的。如果您想用旧版本替换内容(例如,需要恢复为旧版本而没有引入错误的JavaScript文件),并且在使用文件的旧日期时,那么简单的日期比较将不足以满足要求。 – 2017-01-23 08:55:49

回答

0

也许你使用一个操纵HTTP请求的(squid)代理?

+0

不,我没有使用任何代理。我甚至尝试在我的本地主机。同样的结果。 – Sabya 2009-05-22 09:20:40

19

这是Apache中已知的一个bug。见Apache bug #45023summary of Apache 304 etags and mod_deflate

从svn重建将解决这个问题。解决方案是恢复附加“-gzip”到etag的更改。但是,存在关联的HTTP合规性问题。

如果不能重建Apache的,没有在bug报告建议运行时配置的解决方法:

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

“我还决定,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 

测试用例:

    “2E2 -5388f9f70c580-afeg“
    “2e2-5388f9f70c580-gzin”
    “2e2-5388f9f70c580-gzipd”
    “2e2-5388f9f70c580gzip”
    “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'" 


我个人使用下面的代码,如果它是一个gzip响应,并且不重新使用它,那么它会首先去掉'-gzip'部分,所以浏览器永远不会发送'-gzip'标头。

Header edit ETag "(.+)-gzip\"$" "$1\"" "expr=resp('Content-Encoding') == 'gzip'"