Apache 2.4.7 игнорирует заголовок ответа Content-Encoding: идентичность, вместо этого учитывает Content-Encoding: нет, устанавливается PHP
Я только что понял свою очевидную проблему (и "решение" Content-Encoding: none
из вопроса StackOverflow, о котором я упоминал в своем первоначальном вопросе ниже), вполне может быть просто из-за неправильного понимания того, как все работает на самом деле. Пожалуйста, просмотрите мое приложение в конце.
В PHP-приложении, которое я создаю, я пытаюсь управлять своими собственными согласованиями и сжатием кодировки контента.
Когда я устанавливаю заголовок ответа Content-Encoding
из PHP либо gzip
или же deflate
Apache уважает это. Тем не менее, когда я установил его на identity
Apache игнорирует это и сжимает ответ.
Это только кажется уважать нестандартное Content-Encoding: none
, как я нашел в некоторых ответах и их комментариях в этом вопросе переполнения стека.
Я поэтому в настоящее время устанавливаю это none
изнутри PHP и затем изменяя заголовок через .htaccess
с:
Header edit Content-Encoding ^none$ identity
... но это действительно похоже на уродливый хак. Я бы хотел, чтобы мне не приходилось делать это, на случай, если я когда-нибудь переключу серверы, например.
Это известная проблема и / или это нестандартное поведение где-то задокументировано? Я не могу найти какую-либо конкретную документацию по этому поводу.
Я также искал трекер ошибок Apache, но смог найти только отчет об ошибках, связанных с тангенциально, о том, что Apache не уважает Accept-Encoding
значения заголовка.
добавление
Когда я отключаю Apache mod_deflate в .htaccess
с (есть и другие варианты для этого):
SetEnv no-gzip 1
... и установить Content-Encoding: identity
изнутри PHP Apache сохраняет этот заголовок и содержимое без изменений, просто отлично.
Поэтому вот что, на мой взгляд, происходит на самом деле:
Это не то Content-Encoding: none
это какой-то официальный сигнал к Apache, чтобы отключить сжатие (Content-Encoding: bogus
например, дает тот же результат), что объясняет, почему я не смог найти никакой документации по этому поводу.
Скорее, это просто значение, которое не является стандартом RFC. Поэтому mod_deflate оставляет контент нетронутым, предполагая, что это какая-то нестандартная кодировка, которой он не хочет мешать.
Итак, когда я установил Content-Encoding: identity
из PHP, mod_deflate, вероятно, распознает это как действительный стандарт RFC, что означает, что контент еще не был сжат, и, поскольку mod_deflate включен, выполняется его дальнейшее сжатие.
Кроме того, если я установлю Content-Encoding
в gzip
или же deflate
например, mod_deflate, вероятно, либо оставляет его нетронутым полностью, либо пытается сжимать его в любом случае, но алгоритм сжатия распознает, что контент уже был сжат.
Может ли кто-нибудь подтвердить, является ли это правильной интерпретацией того, что на самом деле происходит?
Таким образом, возможным решением было бы либо отключить mod_deflate для некоторых выбранных файлов / путей, которыми управляет мое PHP-приложение, либо, возможно, даже вообще отключить mod_deflate/site-wide/server-wide, если весь мой контент уже был сжат каким-либо другим способом.
1 ответ
Итак, мне удалось решить мои проблемы, принимая во внимание предположения, которые я изложил в своем вопросе, и которые кажутся правильными. Но не без борьбы.
При попытке реализовать его только для контента, сгенерированного PHP, я столкнулся с некоторыми другими проблемами, которые я опишу здесь:
У меня изначально были следующие правила переписать в моем .htaccess
:
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
С RewriteRule
флаги, вы должны иметь возможность устанавливать переменные среды. Итак, я решил, что должен быть в состоянии установить E=no-gzip:1
помечать только последний RewriteRule
, при выполнении:
RewriteRule ^.*$ index.php [NC,E=no-gzip:1,L]
И хотя ранее упоминалось
SetEnv no-gzip 1
работал нормально, RewriteRule
флаг просто не прижился Затем я посмотрел на различные вопросы о переполнении стека, например, этот, этот. Но они не предлагали удовлетворительных решений.
Затем я на мгновение прибегнул к установке переменной среды изнутри PHP с помощью apache_setenv( 'no-gzip', 1 );
, который сделал свое дело. Но это просто не правильно и заставило меня задуматься, почему, черт возьми RewriteRule
флаг не будет работать так же хорошо.
Затем я решил сделать var_dump( $_SERVER )
, чтобы увидеть, является ли RewriteRule
Флаг был фактически установлен, только чтобы столкнуться со старой Немезидой, о которой я забыл:
array(39) {
["REDIRECT_no-gzip"]=>
string(1) "1"
["REDIRECT_APP_ENV"]=>
string(11) "development"
/* etc. */
}
Черт REDIRECT_
это добавляется к переменным окружения при перезаписи.
У меня сложилось впечатление, что L
флаг на моем последнем RewriteRule
должно означать перестать переписывать, но, видимо, я неверно истолковал это правило и его условия:
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l
RewriteRule ^.*$ - [NC,L]
поскольку RewriteRule ^.*$ index.php [NC,E=no-gzip:1,L]
переписывает index.php
, который является обычным файлом (-s
), вышеупомянутые условия и правила все еще действуют.
Теперь, когда я изменил это правило на
RewriteRule !^index.php - [NC,L]
все наконец работает как хотелось!