Apache mod_header 奇怪的行为

Apache mod_header strange behavior

############################
# FILES - CACHING: CONTROL #
############################

Header set Cache-Control "max-age=2592000, public"

<FilesMatch "\.(?:bmp|css|cur|gif|ico|jp(?:eg?|g)|js|png|svgz?|tiff?|webp)$">
    Header set Cache-Control "max-age=31536000, public"
</FilesMatch>

<FilesMatch "\.(?:html?|json|php|xml)$">
    Header set Cache-Control "max-age=0, must-revalidate, no-cache, no-store, post-check=0, pre-check=0, private"
</FilesMatch>

<FilesMatch "\.(?:atom|rdf|rss)$">
    Header set Cache-Control "max-age=3600, public"
</FilesMatch>

Header merge Cache-Control "no-transform"

这是我的 htacces 的片段,我在其中处理了 Cache-Control header。默认情况下,对于所有文件,它设置为 max-age=2592000, public。 在底部,我总是试图附加一个 no-transform 指令,但它根本不起作用。它……嗯,它什么都不做。 no-transform 指令从未被设置。我尝试用 append 替换 merge,没有任何变化。

现在,这就是我注意到的。如果我将第三个 FilesMatch 指令替换为:

<FilesMatch "\.(?:atom|rdf|rss)$">
    Header set Cache-Control "max-age=3600, public"
    Header merge Cache-Control "no-transform"
</FilesMatch>

有效。我站点的每个提要文件都将包含 no-transform 指令。如果我将第一个代码段的最后一行更改为:

<FilesMatch "^.+$">
    Header merge Cache-Control "no-transform"
</FilesMatch>

嗯...它适用于所有文件。只是……为什么?!

我还注意到另一个关于 headers 的非常奇怪的行为。假设我想在连接上强制使用 keep-alive。我将其插入我的 htaccess 文件中的某处:

Header merge Connection "Keep-Alive"

这就是我在回复中得到的 header:

Connection: Keep-Alive, Keep-Alive

再次……为什么?!

我怀疑(虽然找不到任何文档来支持这一点,因为它不是 100% 从这个页面清楚:https://httpd.apache.org/docs/2.4/sections.html),FilesMatch 指令是在不在 FileMatch 中的指令之后处理的。

因此即使你这样写:

Header set Cache-Control "max-age=2592000, public"

<FilesMatch "\.(?:atom|rdf|rss)$">
    Header set Cache-Control "max-age=3600, public"
</FilesMatch>

Header merge Cache-Control "no-transform"

Apache 是这样处理的:

Header set Cache-Control "max-age=2592000, public"

Header merge Cache-Control "no-transform"

<FilesMatch "\.(?:atom|rdf|rss)$">
    Header set Cache-Control "max-age=3600, public"
</FilesMatch>

这意味着 "later" 集会覆盖之前的合并。如果您将 FilesMatch 片段中的 "set" 更改为 "merge",您应该会看到它起作用,因为它将不再覆盖它。

老实说,我认为这种编写配置的方式很难遵循。既然您将缓存控制 header 设置了四次,为什么不在四个 set 指令中的每一个中同时设置 no-transform 呢?是的,这是一点点重复,但更清晰,意味着您不会 运行 陷入这些订单问题!

你的第二个问题从文档中更容易解释:http://httpd.apache.org/docs/current/mod/mod_headers.html#header:

merge ... Values in double quotes are considered different from otherwise identical unquoted values

因此,如果值为 Keep-Alive 并且您添加 "Keep-Alive",那么您最终会得到 "Keep-Alive Keep-Alive"。

顺便说一句,您应该 而不是 尝试通过设置 header 来启用 Keep-Alives。虽然这对客户端有效,但 Apache 还需要保持连接处于活动状态以供客户端连接,这不仅仅是通过设置 header 来实现的。所以客户端会认为连接正在保持活动状态,但实际上它不会,因为服务器无论如何都会关闭连接。您需要使用如下配置对其进行设置(这还将为您设置必要的 headers):

KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5