<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 Not Modified响应永远不会返回标头,即使它返回其他适当的Apache标头。
如何在304响应期间设置标头?
答案 0 :(得分:7)
根据当前的HTTP规范,304 Not Modified
响应不应该返回实体头(除了一些特定的例外)。引自section 10.3.5 of RFC 2616:
如果条件GET使用了强缓存验证器,则响应不应该包含其他实体头。 否则(即,条件GET使用弱验证器),响应绝不能包括其他实体头;这可以防止缓存的实体主体和更新的标头之间出现不一致。
不幸的是,所有扩展标头都是classified as entity headers。
然而,展望未来,在旨在取代RFC 2616的HTTPbis规范草案中,规则要宽松得多。引自section 4.1 of the Conditional Requests spec:
因为304响应的目标是最小化信息传输 当收件人已经有一个或多个缓存的表示时,a 发送者不应该生成除了。之外的表示元数据 以上列出的字段除非所述元数据存在于此目的 指导缓存更新。
因此,如果您要设置一个不会被归类为表示元数据的自定义标头,那么我希望根据新规则将其视为合法。
尽管如此,无论这些规范中写了什么,您仍然需要处理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)时,上面的标题列表是唯一允许通过的标题(除了一些自动生成的标题,例如 Date 和服务器)。从我所看到的,似乎没有一种简单的方法来挂钩这段代码来改变行为。
最重要的是,目前在Apache中仍然无法做到这一点。至少one bug report请求支持其他标头,但这是专门针对CORS标头的。但幸运的是,这可能会鼓励他们更加开放地支持自定义标题。
但在此之前,我建议的唯一解决方案是自己修补服务器。如果您不想从源代码重建,您甚至可以直接修补二进制文件。例如,如果您只需要支持一个或两个新标头,则可以替换一些您不太可能使用的现有标头(例如 Set-Cookie2 ,无论如何都是过时的)。
只需在Apache bin目录中搜索要替换的标题名称(在Windows上,您应该在 libhttpd.dll 中找到它们)。然后使用二进制编辑器将以null结尾的字符串替换为新的标题名称(当然,它需要与您要替换的标题长度相同或更短)。
我不了解其他操作系统,但我在Windows上测试了它,它似乎确实有效。这显然是一个可怕的黑客,但如果你非常绝望,你可能会认为这是一个选择。
答案 1 :(得分:1)
Apache明确禁止修改304响应中的响应头以符合http规范。此类响应的名称是&#34;未修改&#34;。您可以使用Apache的过滤器体系结构,编写自定义模块或使用mod_perl来修改此行为,但这很可能是错误的。