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]
все наконец работает как хотелось!