Apache не отправляет ответ 304 (если включены mod_deflate и AddOutputFilterByType) - PullRequest
25 голосов
/ 22 мая 2009

Я добавил следующую строку в мой 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?

Если я закомментирую строку «AddOutputFilterByType» в httpd.conf, Apache отправит 304.

Если я включу AddOutputFilterByType в httpd.conf, заголовок запроса будет: -

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 таким, какой он есть (я знаю, что существует проблема с раскрытием инода).

Ответы [ 4 ]

25 голосов
/ 09 июля 2009

Это известная ошибка в Apache. См. Ошибка Apache # 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\""
9 голосов
/ 27 июля 2016

«Я также решил, что 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, поэтому я написал лучший код, чем выше, чтобы решить эту проблему. Расширение построчно:


Вы можете использовать как отрицательный, так и отрицательный взгляд, скорость регулярного выражения одинакова, 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'"


Лично я использую следующий код, который сначала удаляет часть -gzip, если это ответ gzip, и не перезапускает его, поэтому браузер никогда не отправит заголовок * -5454 * -gzip.

Header edit ETag "(.+)-gzip\"$" "$1\"" "expr=resp('Content-Encoding') == 'gzip'"
2 голосов
/ 19 мая 2017

Я знаю, что это очень старый вопрос, но, похоже, есть более актуальный ответ.

Чтобы Apache не добавлял суффикс -gzip, необходимо использовать директиву DeflateAlterETag со значением NoChange.

См. Документацию для этого здесь: http://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag

0 голосов
/ 22 мая 2009

Может быть, вы используете прокси (squid), который манипулирует HTTP-запросами?

...