Я только что осознал свою очевидную проблему (и "решение" 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]
наконец то все заработало как надо!