httpd-38017
Version:
2.2.0
How it is diagnosed (reproduced or source analysis)?
Source analysis (we cannot reproduce it).
Symptom:
Apache cache refuse to serve any cached content, so every request needs to go to the back-end server even if the local cache had cached the object.
When apache is configured as “mod_cache + mod_disk_cache + mod_proxy + mod_proxy_ajp” as a reverse caching proxy. The backend server (tomcat) sets all the right http headers (Expires, Last-Modified) but apache refuses to serve cached content. The same problem also shows up with mod_mem_cache and/or mod_proxy_http
Root cause:
Inconsistency in storing & look-up of cache object: object storing is using the canonized name “_default_”, while during look-up it did not canonize, directly search using the actual name. This makes httpd thinks the content is not cached...
cache_storage.c
320: apr_status_t cache_generate_key_default(...) {
...
/* Use the canonical name to improve cache hit rate, but only if this is
* not a proxy request.
*/
- if (!r->proxyreq) {
+ if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) {
// In the buggy run, ‘r->proxyreq == PROXYREQ_REVERSE’, so it was set to ‘_default_’.
/* Use _default_ as the hostname if none present, as in mod_vhost */
hostname = ap_get_server_name(r);
if (!hostname) {
hostname = "_default_";
}
}
else if(r->parsed_uri.hostname) {
...
}
else {
/* We are a proxied request, with no hostname. Unlikely
* to get very far - but just in case */
/* default case of a switch, we should put a log message! */
hostname = "_default_";
}
if (r->proxyreq && r->parsed_uri.scheme) {
... ...
}
else {
scheme = "http";
}
if(r->proxyreq) {
...
}
..
}
Is there Error Message?
No.
Can Errlog anticipate the Error?
Yes. Here, developers are using if.. else if .. else to implement: default-switch. The code logic:
- if (!r->proxyreq) {
… ..
}
else if(r->parsed_uri.hostname) {
...
}
else {
/* We are a proxied request, with no hostname. Unlikely
* to get very far - but just in case */
/* default case of a switch, Errlog will put a log message! */
hostname = "_default_";
}
NOTE:
Squid bug 2678 is very similar to this one. Developers should pay attention to the inconsistency when canonizing file names during store/retrieve.