I'm using Apache 2.4.3 as a reverse proxy due to it's advertised compliance with RFC 2616. My app uses headers like this to enable caching at the proxy:
Cache-Control: public, s-maxage=0
Expires: ... (+1 day)
X-Group: A
Vary: X-Group
ETag: W/"foo1"
After the first request warms the cache, if my app changes to respond with this:
Cache-Control: public, s-maxage=0
Expires: ... (+1 day)
X-Group: B
Vary: X-Group
ETag: W/"foo2"
The app will respond with 304 Not Modified if the If-None-Match header from Apache matches the origin-generated ETag. However, Apache then caches the second 200 response and replaces the "foo1" record with the new response instead of caching both of the responses with different ETags. Therefore, instead of If-None-Match: W/"foo1", W/"foo2"
the next revalidate request is just If-None-Match: W/"foo2"
. So the cache is constantly getting misses instead of always getting hits.
From the RFC 2616 section 12.1:
However, an origin server is not limited to these dimensions and MAY vary the response based on any aspect of the request, including information outside the request-header fields or within extension header fields not defined by this specification.
I've tried the following combinations for Vary:
Vary: X-Foo
Vary: *
Vary: User-Agent
I've also tried both strong and weak ETags and no matter what I cannot get Apache to cache the two responses simultaneously, it always saves over the previous one. If it can't save more than one variance of a page then ETag is useless, Last-Modified would be just as good.
From the Apache 2.4 docs:
mod_cache implements an RFC 2616 compliant HTTP content caching filter, with support for the caching of content negotiated responses containing the Vary header.
Note that it says "responses" plural. Am I mis-interpreting the HTTP spec or does Apache 2.4 just not fully support ETags after-all?
You give a couple of examples like this:
I notice in particular the
Vary: X-Group
header. IsX-Group
a request header or a response header?As per RFC 2616 section 14.44,
Vary
should list any request headers that will result in a different content representation from an origin server. From your example, I suspectX-Group
might be a response header, in which case mod_cache won't be storing multiple versions of the given resource.One thing you could try would be to set
Vary: If-None-Match
, which would let mod_cache store a version of the resource for each ETag. Admittedly, I haven't tried this. Assuming it works, one downside is that the first request from any client would be a cache miss.