根据当前的 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 响应的目标是最大程度地减少信息传输
当接收者已经有一个或多个缓存表示时,一个
发件人不应该生成除
上面列出的字段,除非所述元数据存在的目的是
指导缓存更新。
因此,如果您设置的自定义标头不会被归类为表示元数据,那么我希望根据新规则,这将被视为合法。
也就是说,无论这些规范中写了什么,您仍然必须处理 Apache 可以支持的内容。而且从我在源代码中看到的情况来看,304 响应中仍然不支持自定义标头。
headers被过滤的地方在文件/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 中找到它们)。然后使用二进制编辑器将以空字符结尾的字符串替换为您的新标头名称(当然,它需要与您要替换的标头长度相同或更短)。
我不了解其他操作系统,但我已经在 Windows 上对此进行了测试,它似乎确实可以工作。这显然是一个可怕的 hack,但如果你足够绝望,你可能会考虑它。