Назад | Перейти на главную страницу

Apache 2.4.7 игнорирует заголовок ответа Content-Encoding: identity, вместо этого учитывает Content-Encoding: none, установленный 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 значения заголовка.


Дополнение

Когда я отключаю mod_deflate Apache в .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 полностью / на уровне сайта / на уровне сервера, если все мой контент уже был сжат каким-то другим способом.

Итак, мне удалось решить свои проблемы, приняв во внимание предположения, изложенные в моем вопросе, которые кажутся правильными. Но не без борьбы.

Пытаясь реализовать его только для контента, созданного 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 flag не будет работать так же хорошо.

Затем я решил сделать 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]

наконец то все заработало как надо!