根据当前的 HTTP 规范,304 Not Modified
响应不应该返回实体标头(除了一些特定的例外)。引用RFC 2616 的第 10.3.5 节:
如果条件 GET 使用了强缓存验证器,则响应不应包含其他实体标头。否则(即,条件 GET 使用弱验证器),响应不得包含其他实体标头;这可以防止缓存的实体主体和更新的标头之间的不一致。
不幸的是,所有扩展标头都被归类为实体标头。
然而,展望未来,在旨在取代 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) 时,上面的标头列表是唯一允许通过的标头(除了一些自动生成的标头,例如Date和Server)。从我所见,似乎没有一种简单的方法可以连接到这段代码来改变行为。
最重要的是,目前这在 Apache 中仍然是不可能的。至少有一个错误报告请求支持其他标头,但这是专门针对 CORS 标头的。不过,如果运气好的话,这可能会鼓励他们对支持自定义标头更加开放。
但在此之前,我可以建议的唯一解决方案是自己修补服务器。如果您不想从源代码重建,您甚至可以直接修补二进制文件。例如,如果您只需要支持一个或两个新标头,您可以替换一些您不太可能使用的现有标头(例如Set-Cookie2,无论如何它已经过时了)。
只需在 Apache bin 目录中搜索要替换的标头名称(在 Windows 上,您应该在libhttpd.dll中找到它们)。然后使用二进制编辑器用您的新标题名称替换以空字符结尾的字符串(当然它需要与您要替换的标题相同或更短)。
我不知道其他操作系统,但我已经在 Windows 上进行了测试,它似乎确实有效。这显然是一个可怕的黑客,但如果你足够绝望,你可能会考虑它。