Apache is not sending 304 response (if mod_deflate and AddOutputFilterByType is enabled)

后端 未结 4 1976
渐次进展
渐次进展 2020-12-02 21:05

I have added the following line in my Apache httpd.conf: -

AddOutputFilterByType DEFLATE text/html text/css application/javascript application/x-javascript a         


        
相关标签:
4条回答
  • 2020-12-02 21:19

    This is a known bug in Apache. See Apache bug #45023, and summary of Apache 304 etags and mod_deflate.

    Rebuilding from svn will fix the issue. The resolution was to revert the change that appended "-gzip" to the etag. However, there are associated HTTP compliance problems.

    If you can't rebuild Apache, there is a suggested runtime configuration workaround in the bug report:

     RequestHeader  edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
     Header  edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""
    
    0 讨论(0)
  • 2020-12-02 21:19

    I know this is a very old question, but it appears there's a more up-to-date answer.

    To have Apache not append the -gzip suffix, you must use the DeflateAlterETag directive with a value of NoChange.

    See the documentation for this here: http://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag

    0 讨论(0)
  • 2020-12-02 21:22

    "I've also decided that ETags aren't that useful in Apache anyway."

    Wrong,
    for example you have a file with modification date set to '2016.07.27 05:00:00', you upload it to your site, browser gets this file with HTTP code 200, then caches it and revalidates every time with HTTP 304.
    Next you upload a file with the same filename again, but with older timestamp '2013.07.27 05:00:00' and with other content.

    If ETag is disabled on server, browser will use only If-Modified-Since: request to determine if file was changed on server, so the request will be If-Modified-Since: 2016.07.27 05:00:00, but the file is not modified after this date, so a HTTP 304 is returned, even if the file has changed.

    If ETag is enabled on server, besides If-Modified-Since:, there will be a If-None-Match: header coming from browser that will detect that file was changed(by default - timestamp mismatch+size mismatch) and the file will be redownloaded.


    This problem still exists in Apache 2.4.23, so, I've written a better code than above to fix this issue. Expanation line by line:

      1) If the browser sends a 'If-None-Match' request which has '-gzip' at the end, set variable request_etag=gzip.
      2) Edit request header to strip out '-gzip' part.
      3) Edit response header to add '-gzip' part, but only if the browser sent a '-gzip' request initially or response content is gzip encoded.


    You can use either negative lookahead or negative lookbehind, regex speed is the same, Apache supports both

    \"(.+(?<!-gzip))\"       #using negative lookbehind
    \"((?:.(?!-gzip\"))+)\"  #using negative lookahead
    

    Test cases:

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

    Copy-Paste this code into 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'"
    


    I personally use the following code, that strips '-gzip' part initially if it's a gzip response, and doesn't reappend it, so the browser will never send a '-gzip' 'If-None-Match' header.

    Header edit ETag "(.+)-gzip\"$" "$1\"" "expr=resp('Content-Encoding') == 'gzip'"
    
    0 讨论(0)
  • 2020-12-02 21:23

    Maybe you use a (squid) proxy which manipulates the HTTP Requests?

    0 讨论(0)
提交回复
热议问题