304响应在使用mod_headers的Apache中无法设置自定义头信息

5
<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>

这是我的配置。我有一个环境变量告诉我我在哪个集群上,在“X-Cluster”标头中传递。这在200或404响应中返回正常,但304未修改的响应从不返回标头,即使它返回其他适当的Apache标头。
我如何在304响应期间设置标头?

有点冒险,但是你找到解决方案了吗? - juan
http://stackoverflow.com/questions/17812347/how-to-add-a-custom-header-despite-a-rewriterule-redirecting-to-304 - juan
2个回答

9
根据当前的HTTP规范,除了特定的几个例外情况,304 Not Modified响应不应该返回实体头。引用自RFC 2616第10.3.5节
如果有条件的GET使用了强缓存验证器,则响应SHOULD NOT包括其他实体头。 否则(即有条件的GET使用了弱验证器),响应MUST NOT包括其他实体头;这可以防止缓存实体主体和更新的头之间的不一致。
不幸的是,所有扩展头都被归类为实体头
然而,展望未来,在旨在取代RFC 2616的草案HTTPbis规范中,规则更加灵活。引用自有条件请求规范第4.1节
由于304响应的目标是在接收者已经拥有一个或多个缓存表示时最小化信息传输,因此除非该元数据存在于指导缓存更新的目的之外,否则发送方不应生成除上述列出的字段以外的表示元数据。
因此,如果您设置了一个不被归类为表示元数据的自定义标头,那么我希望它被认为是符合新规则的合法操作。
话虽如此,无论这些规范中写了什么,您仍然必须处理Apache能够支持的内容。从我在源代码中看到的情况来看,自定义标头仍然不受304响应的支持。
标头被过滤的地方在文件/modules/http/http_filters.c中的ap_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);
}

当返回“未修改”响应(304)时,上述标头列表是唯一允许通过的标头(除了一些自动生成的标头,如DateServer)。从我所看到的情况来看,似乎没有一种简单的方法来钩入此代码以改变行为。

底线是,在目前的Apache版本中仍然不可能实现。至少有一个错误报告要求支持其他标头,但那是特别针对CORS标头的。但带着一点运气,这可能会鼓励他们更加开放地支持自定义标头。

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

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

我不知道其他操作系统的情况,但我已经在Windows上测试过了,它确实可以工作。显然,这是一个可怕的黑客方式,但如果您足够绝望,您可能会考虑这个选项。


3

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接