我刚刚意识到我的问题(以及我在最初的问题中提到的 StackOverflow 问题的“解决方案” Content-Encoding: none
)很可能只是由于误解了事情的实际运作方式。请查看最后的附录。
在我正在构建的 PHP 应用程序中,我正在尝试管理自己的内容编码协商和压缩。
Content-Encoding
当我在 PHP 中将响应标头设置为gzip
或 时deflate
,Apache 会尊重这一点。但是,当我将其设置为 时,identity
Apache 会忽略这一点并压缩响应。
它似乎只尊重非标准Content-Encoding: none
,正如我在一些答案和他们的评论中发现的那样这个 Stack Overflow 问题。
因此,我目前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 可能会完全保持不变,或者尝试压缩它,但压缩算法会识别出内容已经被压缩。
有人可以确认这是否是正确的解释吗?实际上发生了什么?
因此,一个可能的解决方案是,要么针对我的 PHP 应用程序管理的某些选定文件/路径禁用 mod_deflate,要么甚至禁用整个/整个站点/整个服务器的 mod_deflate,如果全部我的内容已经通过其他方式压缩了。
答案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
标志就是不流行。然后我查看了 Stack Overflow 上各种相关问题,例如这个这个.但他们并没有提出令人满意的解决方案。
然后我暂时求助于在 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]
一切终于如预期般顺利!