根据当前的 HTTP 规范,304 Not Modified
响应不应返回实体标头(除了一些特定的例外)。引用自RFC 2616 第 10.3.5 节:
如果条件 GET 使用强缓存验证器,则响应不应包含其他实体标头。
否则(即,条件 GET 使用弱验证器),响应不得包含其他实体标头;这可以防止缓存的实体主体和更新的标头之间出现不一致。
不幸的是所有扩展头都是分类为实体标题.
然而,展望未来,在旨在取代 RFC 2616 的 HTTPbis 规范草案中,规则要宽松得多。引用自条件请求规范第 4.1 节:
由于 304 响应的目标是最大限度地减少信息传输
当接收者已经拥有一个或多个缓存表示时,
发送者不应该生成除
上面列出的字段,除非所述元数据的存在是为了
指导缓存更新。
因此,如果您设置的自定义标头不会被分类为表示元数据,那么我希望根据新规则将其视为合法。
也就是说,无论这些规范中写了什么,您仍然必须处理 Apache 可以支持的内容。从我在源代码中看到的情况来看,304 响应中仍然不支持自定义标头。
过滤header的地方是在ap_http_header_filter文件中的函数/modules/http/http_filters.c:
更具体地说,这段代码:
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 and Server)。据我所知,似乎没有一种简单的方法可以连接到这段代码来改变行为。
最重要的是,目前在 Apache 中这仍然是不可能的。至少有一份错误报告请求对其他标头的支持,但这是专门针对 CORS 标头的。不过,如果幸运的话,这可能会鼓励他们更加开放地支持自定义标头。
但在此之前,我可以建议的唯一解决方案是自己修补服务器。如果您不想从源代码重建,您甚至可以直接修补二进制文件。例如,如果您只需要支持一两个新标头,则可以替换一些您不太可能使用的现有标头(例如设置-Cookie2,无论如何它已经过时了)。
只需在 Apache bin 目录中搜索要替换的标头名称(在 Windows 上,您应该在libhttpd.dll)。然后使用二进制编辑器将空终止字符串替换为新的标头名称(当然,它需要与要替换的标头长度相同或更短)。
我不知道其他操作系统,但我在 Windows 上测试过它,它似乎确实有效。这显然是一个可怕的黑客攻击,但如果你足够绝望,你可能会认为这是一个选择。