304 响应未使用 mod_headers 设置 apache 的自定义标头

发布于 2024-11-05 10:00:20 字数 681 浏览 4 评论 0原文

<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"
    ServerName dev.dom.com
    ServerAlias dev.dom.com
    ErrorLog "logs/dev.dom.com-error.log"
    CustomLog "logs/dev.dom.com-access.log" common
    PassEnv CLUSTER
    Header always set X-Cluster "%{CLUSTER}e"
</VirtualHost>

这是我的配置。我有一个环境变量,它告诉我所在的集群,该变量作为“X-Cluster”中的标头传递。这对 200 或 404 响应返回良好,但 304 Not Modified 响应永远不会返回标头,即使它返回其他适当的 Apache 标头。

如何在 304 响应期间设置标头?

<VirtualHost *:80>
    ServerAdmin [email protected]
    DocumentRoot "C:/Program Files/Apache Software Foundation/Apache2.2/htdocs"
    ServerName dev.dom.com
    ServerAlias dev.dom.com
    ErrorLog "logs/dev.dom.com-error.log"
    CustomLog "logs/dev.dom.com-access.log" common
    PassEnv CLUSTER
    Header always set X-Cluster "%{CLUSTER}e"
</VirtualHost>

Here is my configuration. I have an environment variable which tells me what cluster I am on, which is passed as a header in 'X-Cluster'. This returns fine on a 200 or a 404 response, but a 304 Not Modified response never returns the header, even though it returns other appropriate Apache headers.

How do I get the header to be set during a 304 response?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情魔剑神 2024-11-12 10:00:20

根据当前的 HTTP 规范,304 Not Modified 响应不应返回实体标头(少数特定例外除外)。引用 RFC 2616 第 10.3.5 节

如果条件 GET 使用强缓存验证器,则响应不应包含其他实体标头。
否则(即,条件 GET 使用弱验证器),响应不得包含其他实体标头;这可以防止缓存的实体主体和更新的标头之间出现不一致。

不幸的是,所有扩展标头都归类为实体标头

然而,展望未来,在旨在取代 RFC 2616 的 HTTPbis 规范草案中,规则要宽松得多。引用条件请求的第 4.1 节规格

由于 304 响应的目标是最大限度地减少信息传输
当接收者已经拥有一个或多个缓存表示时,
发送者不应该生成除
上面列出的字段,除非所述元数据的存在是为了
指导缓存更新。

因此,如果您设置的自定义标头不会被归类为表示元数据,那么我希望根据新规则将其视为合法。

也就是说,无论这些规范中写了什么,您仍然必须处理 Apache 可以支持的内容。从我在源代码中看到的情况来看,304 响应中仍然不支持自定义标头。

过滤 headers 的地方在文件 /modules/http/http_filters.c

更具体地说,此代码:

if (r->status == HTTP_NOT_MODIFIED) {
    apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
                 (void *) &h, r->headers_out,
                 "Connection",
                 "Keep-Alive",
                 "ETag",
                 "Content-Location",
                 "Expires",
                 "Cache-Control",
                 "Vary",
                 "Warning",
                 "WWW-Authenticate",
                 "Proxy-Authenticate",
                 "Set-Cookie",
                 "Set-Cookie2",
                 NULL);
}

当返回“未修改”响应(304)时,上面的标头列表是仅允许通过的标头(除了一些自动生成的标头,例如 DateServer)。据我所知,似乎没有一种简单的方法可以连接到这段代码来改变行为。

最重要的是,目前在 Apache 中这仍然是不可能的。至少有一个错误报告请求支持其他标头,但是这是专门针对 CORS 标头的。不过,如果幸运的话,这可能会鼓励他们更加开放地支持自定义标头。

但在此之前,我可以建议的唯一解决方案是自己修补服务器。如果您不想从源代码重建,您甚至可以直接修补二进制文件。例如,如果您只需要支持一两个新标头,则可以替换一些您不太可能使用的现有标头(例如 Set-Cookie2,无论如何它都已过时)。

只需在 Apache bin 目录中搜索要替换的标头名称(在 Windows 上,您应该在 libhttpd.dll 中找到它们)。然后使用二进制编辑器将空终止字符串替换为新的标头名称(当然,它需要与要替换的标头长度相同或更短)。

我不知道其他操作系统,但我在 Windows 上测试过它,它似乎确实有效。这显然是一个可怕的黑客行为,但如果你足够绝望,你可能会认为这是一个选择。

According to the current HTTP spec, a 304 Not Modified response is not supposed to return entity headers (except for a few specific exceptions). Quoting from section 10.3.5 of RFC 2616:

If the conditional GET used a strong cache validator, the response SHOULD NOT include other entity-headers.
Otherwise (i.e., the conditional GET used a weak validator), the response MUST NOT include other entity-headers; this prevents inconsistencies between cached entity-bodies and updated headers.

And unfortunately all extension headers are classified as entity headers.

However, looking to the future, in the draft HTTPbis spec that is intended to replace RFC 2616, the rules are much more relaxed. Quoting from section 4.1 of the Conditional Requests spec:

Since the goal of a 304 response is to minimize information transfer
when the recipient already has one or more cached representations, a
sender SHOULD NOT generate representation metadata other than the
above listed fields unless said metadata exists for the purpose of
guiding cache updates.

So if you are setting a custom header that wouldn't be classified as representation metadata, then I would expect that to be considered legal under the new rules.

That said, no matter what is written in these specifications, you still have to deal with what Apache can support. And from what I've seen in the source code, custom headers are still not supported in a 304 response.

The place where the headers are filtered is in the ap_http_header_filter function in the file /modules/http/http_filters.c:

More specifically, this code:

if (r->status == HTTP_NOT_MODIFIED) {
    apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
                 (void *) &h, r->headers_out,
                 "Connection",
                 "Keep-Alive",
                 "ETag",
                 "Content-Location",
                 "Expires",
                 "Cache-Control",
                 "Vary",
                 "Warning",
                 "WWW-Authenticate",
                 "Proxy-Authenticate",
                 "Set-Cookie",
                 "Set-Cookie2",
                 NULL);
}

When returning a "Not Modified" response (304), the above list of headers are the only ones that are let through (other than a few automatically generated headers, like Date and Server). And from what I can see, there doesn't appear to be an easy way to hook into this code to alter the behaviour.

The bottom line is that this is still not possible in Apache at the current time. There is at least one bug report requesting support for other headers, but that is specifically for the CORS headers. With any luck, though, that may encourage them to be more open to supporting custom headers in general.

But until that happens, the only solution I can suggest is to patch the server yourself. If you don't want to have to rebuild from source, you could even patch the binaries directly. For example, if you only need to support one or two new headers, you could replace some of the existing headers that you aren't likely to use (e.g. Set-Cookie2, which is obsolete anyway).

Just search for the header names you want to replace in the Apache bin directory (on Windows you should find them in libhttpd.dll). Then use a binary editor to replace the null-terminated string with your new header name (of course it would need to be the same length or shorter than the header you are replacing).

I don't know about other operating systems, but I've tested this on Windows and it does seem to work. It is obviously a horrible hack, but if you are desperate enough, you might consider it an option.

回眸一遍 2024-11-12 10:00:20

Apache 明确禁止修改 304 响应中的响应标头以符合 http 规范。这种类型的响应的名称是“未修改”。您可以使用 Apache 的过滤器架构、编写自定义模块或使用 mod_perl 来修改此行为,但这很可能是错误的做法。

Apache explicitly prohibits modifying the response headers in a 304 response for compliance with the http spec. The name of this type of response is "Not modified". You can modify this behavior using Apache's filter architecture, by writing a custom module, or with mod_perl perhaps, but it's most likely the wrong thing to do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文