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.