we are trying to use mod_proxy/mod_cache as a `reverse proxy' in front of our webserver. In our configuration, we would like Apache to cache all responses from our server, but revalidate them for every new request. To do that, we are sending Etag headers and force revalidation using "Cache-Control: max-age=0,must-revalidate".
First off, what version are you planning to use? httpd 2.0.53 has a bunch of important fixes for the revalidation functionality. The httpd trunk in SVN (2.1.3-dev as of right now) has a lot more fixes that are probably going to be important to seeing this work as a whole.
Your patch below is against 2.1.2-alpha, so that partially answers that question. 2.1.2-alpha should contains most of the recent fixes, but you should try to follow trunk for now. (Once 2.0.53 is out, I hope to issue another 2.1.alpha release soon.)
- When a client connects for the first time, Apache asks our server (code 200), caches the response (including the Etag header) and sends it to the server (code 200), caching the Etag header received. (This works!)
- When a client (which keeps its own cache) connects for the second time, Apache finds the cached response, revalidates with our server, receives code 304 and sends it back to the client.
(This happens to work, because the client itself sends along "If-None-Match: <our-etag>" in this case.)
- When a different client (which does not have our Etag in its cache) connects, Apache should find the cached response for the URL, revalidate with our server, receive code 304 from our server and send the cached response to the client (code 200).
The last situation is what does not work -- our server does not receive an If-None-Match header from Apache in this case.
Has it passed the age check? Oh, wait, your server is setting 'max-age=0,must-revalidate'. Okay, so, you'd expect to see that every time.
Questions: 0. Is this supposed to work at all?
Yes. Whether it does or not is up for discussion. =)
mod_cache has recently undergone a lot of work to make it better, but there might be some corner cases that aren't quite right yet.
1. Looking briefly at the mod_cache source code, there appear to be cases dealing with this. In cache_select_url(), info->etag is looked at to decide whether "If-None-Match" should be inserted into the request.
However, info->etag is null at this point.
If I hack this check so that the etag header is looked up from the cached response (see patch below), things work better and our server replies with 304.
Hmm. That shouldn't be necessary. The recall_headers function should be loading this value.
Which cache provider are you using? mod_disk_cache or mod_mem_cache? I can only attest that mod_disk_cache works - I don't know anything about mod_mem_cache.
However,
2. Apache then sends the 304 response along to the client, although the client did not send a conditional request at all and needs the full cached response.
There is a check in cache_save_filter() ("Were we initially a conditional request?"), but that check is not reached in this situation.
Again, it should be.
Okay, I just tried a reproduction of what I think you are doing and I found two obscenely small one-line bugs. I just committed fixes in r151815 and r151816. Can you please try trunk? I expect it might work now. =)
Thanks! -- justin