304 response does not set custom header for apache with mod_headers

安稳与你 提交于 2019-12-07 07:44:25

问题


<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>

Here is my configuration. I have an environment variable which tells me what cluster I am on, which is passed as a header in 'X-Cluster'. This returns fine on a 200 or a 404 response, but a 304 Not Modified response never returns the header, even though it returns other appropriate Apache headers.

How do I get the header to be set during a 304 response?


回答1:


Apache explicitly prohibits modifying the response headers in a 304 response for compliance with the http spec. The name of this type of response is "Not modified". You can modify this behavior using Apache's filter architecture, by writing a custom module, or with mod_perl perhaps, but it's most likely the wrong thing to do.




回答2:


According to the current HTTP spec, a 304 Not Modified response is not supposed to return entity headers (except for a few specific exceptions). Quoting from section 10.3.5 of RFC 2616:

If the conditional GET used a strong cache validator, the response SHOULD NOT include other entity-headers. Otherwise (i.e., the conditional GET used a weak validator), the response MUST NOT include other entity-headers; this prevents inconsistencies between cached entity-bodies and updated headers.

And unfortunately all extension headers are classified as entity headers.

However, looking to the future, in the draft HTTPbis spec that is intended to replace RFC 2616, the rules are much more relaxed. Quoting from section 4.1 of the Conditional Requests spec:

Since the goal of a 304 response is to minimize information transfer when the recipient already has one or more cached representations, a sender SHOULD NOT generate representation metadata other than the above listed fields unless said metadata exists for the purpose of guiding cache updates.

So if you are setting a custom header that wouldn't be classified as representation metadata, then I would expect that to be considered legal under the new rules.

That said, no matter what is written in these specifications, you still have to deal with what Apache can support. And from what I've seen in the source code, custom headers are still not supported in a 304 response.

The place where the headers are filtered is in the ap_http_header_filter function in the file /modules/http/http_filters.c:

More specifically, this code:

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);
}

When returning a "Not Modified" response (304), the above list of headers are the only ones that are let through (other than a few automatically generated headers, like Date and Server). And from what I can see, there doesn't appear to be an easy way to hook into this code to alter the behaviour.

The bottom line is that this is still not possible in Apache at the current time. There is at least one bug report requesting support for other headers, but that is specifically for the CORS headers. With any luck, though, that may encourage them to be more open to supporting custom headers in general.

But until that happens, the only solution I can suggest is to patch the server yourself. If you don't want to have to rebuild from source, you could even patch the binaries directly. For example, if you only need to support one or two new headers, you could replace some of the existing headers that you aren't likely to use (e.g. Set-Cookie2, which is obsolete anyway).

Just search for the header names you want to replace in the Apache bin directory (on Windows you should find them in libhttpd.dll). Then use a binary editor to replace the null-terminated string with your new header name (of course it would need to be the same length or shorter than the header you are replacing).

I don't know about other operating systems, but I've tested this on Windows and it does seem to work. It is obviously a horrible hack, but if you are desperate enough, you might consider it an option.



来源:https://stackoverflow.com/questions/5926452/304-response-does-not-set-custom-header-for-apache-with-mod-headers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!