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

时间:2011-05-08 08:42:12

标签: 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>

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

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

2 个答案:

答案 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来修改此行为,但这很可能是错误的。