我刚刚意识到我的明显问题(以及我在前面提到的问题中提到的StackOverflow问题中的“解决scheme” Content-Encoding: none )很可能只是由于误解实际上是如何工作的。 请在最后查看我的附录。
在我正在构build的PHP应用程序中,我试图pipe理自己的内容编码协商和压缩。
当我将响应头Content-Encoding从PHP内部设置为gzip或deflate ,Apache尊重这一点。 但是,当我将其设置为identity Apache忽略这一点,并压缩响应。
它似乎只尊重非标准的Content-Encoding: none ,因为我在这个堆栈溢出问题的一些答案和他们的评论中发现。
因此,我现在把它设置为none ,从PHP内部,然后通过.htaccess更改标题:
Header edit Content-Encoding ^none$ identity
…但这真的感觉像一个丑陋的黑客。 我希望我不必这样做,以防万一我切换服务器,例如。
这是一个已知的问题和/或这种非标准的行为logging在某处? 我似乎无法find任何具体的文件。
我也search了Apache的bug追踪器 ,但只能find一个切线相关的bug报告 ,关于Apache不尊重Accept-Encoding头值。
附录
当我在.htaccess禁用Apache的mod_deflate时(还有其他选项可以做到这一点):
SetEnv no-gzip 1
…并在PHP中设置Content-Encoding: identity ,Apache保持这个标题和内容完好,就好了。
因此,这是我认为实际发生的事情:
这不是Content-Encoding: none官方的信号给Apache来禁止压缩( Content-Encoding: bogus ,例如,产生相同的结果),这将解释为什么我找不到任何文档。
相反,它只是一个不是RFC标准的值。 因此mod_deflate保持内容不变,假设它是一些不想要干扰的非标准编码。
所以,当我在PHP中设置Content-Encoding: identity ,mod_deflate可能认为这是一个有效的RFC标准,意味着内容还没有被压缩,而且由于启用了mod_deflate,所以继续压缩它。
此外,如果我将Content-Encoding设置为gzip或deflate ,例如,mod_deflate可能会将其完全保留,或尝试压缩,但压缩algorithm会识别内容已被压缩。
也许有人可以证实这是否是对实际发生的事情的正确解释?
所以,一个可能的解决scheme是要么禁用我的PHP应用程序pipe理的一些选定的文件/path的mod_deflate,要么如果我的内容已经以其他方式压缩了,甚至可以禁用mod_deflate /站点范围/服务器范围。
所以,我已经设法解决了我的问题,考虑到我在我的问题中提出的假设,这似乎是正确的。 但不是没有挣扎。
试图只为PHP生成的内容实现它,我遇到了一些其他问题,我将在这里描述:
我最初在我的.htaccess有以下重写规则:
RewriteCond %{REQUEST_FILENAME} -s [OR] RewriteCond %{REQUEST_FILENAME} -l RewriteRule ^.*$ - [NC,L] RewriteRule ^.*$ index.php [NC,L]
使用RewriteRule标志,你应该能够设置环境variables 。 所以,我想我应该可以在最后一个RewriteRule上设置E=no-gzip:1标志,方法是:
RewriteRule ^.*$ index.php [NC,E=no-gzip:1,L]
尽pipe前面提到过
SetEnv no-gzip 1
工作得很好, RewriteRule标志只是不能赶上。 然后我研究了Stack Overflow的各种相关问题,比如这一个 。 但是他们没有提供满意的解决scheme。
然后我暂时用apache_setenv( 'no-gzip', 1 );来设置PHP中的环境variablesapache_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_在重写时会被添加到环境variables中。
我的印象是,我最后一个RewriteRule上的L标志应该是停止重写,但显然我错误地解释了这个规则,这是条件:
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]
一切都终于如愿工作!