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]

все наконец работает как хотелось!

Другие вопросы по тегам