304响应没有为mod_headers设置apache的自定义标头

Dom*_*nic 5 apache http-headers http-status-code-304

<VirtualHost *:80>
    ServerAdmin webmaster@dev.dom.com
    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>
Run Code Online (Sandbox Code Playgroud)

这是我的配置.我有一个环境变量,它告诉我我在哪个集群,它在'X-Cluster'中作为标题传递.这在200或404响应上返回正常,但304 Not Modified响应永远不会返回标头,即使它返回其他适当的Apache标头.

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

Jam*_*ess 7

根据当前的HTTP规范,304 Not Modified响应不应该返回实体头(除了一些特定的例外).引用RFC 2616的第10.3.5节:

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

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

但是,展望未来,在旨在取代RFC 2616的HTTPbis规范草案中,规则要宽松得多.引自条件请求规范的4.1节:

由于304响应的目标是在接收方已经具有一个或多个高速缓存表示时最小化信息传输,因此发送方不应该生成除了上面列出的字段之外的表示元数据,除非存在用于指导高速缓存更新的所述元数据.

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

也就是说,无论这些规范中写了什么,您仍然需要处理Apache可以支持的内容.根据我在源代码中看到的内容,304响应中仍然不支持自定义标头.

过滤标头的位置在文件/modules/http/http_filters.cap_http_header_filter函数中:

更具体地说,这段代码:

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);
}
Run Code Online (Sandbox Code Playgroud)

当返回"未修改"响应(304)时,上面的标题列表是唯一允许通过的标题(除了一些自动生成的标题,如日期服务器).从我所看到的,似乎没有一种简单的方法来挂钩这段代码来改变行为.

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

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

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

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


rpl*_*evy 3

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