Hi, The CacheMaxExpire directive is not enforced as stated in the documentation (quote: "This restriction is enforced even if an expiry date was supplied with the document"). After looking at the source of mod_cache.c you can see that the maxexpire value is only used IF the expiration date provided is bad AND the last modified date provided is good. Basically if an expiration date is provided in the document fetched, the CacheMaxExpire value is ignored. I assume it is a bug in the source rather than a bug in the documentation since I think that CacheMaxExpire directive must really be enforced...
I quickly fixed it using this code in mod_proxy.c: Replacing: if (expc == BAD_DATE) { ... } By: { double x = conf->cache.maxexpire; int y = 0; if (expc == BAD_DATE) { if (lmod != BAD_DATE) x = (double)(date - lmod) * conf->cache.lmfactor; else x = conf->cache.defaultexpire; y = 1; } else x = expc - now; if(x > conf->cache.maxexpire) { x = conf->cache.maxexpire; y = 1; } expc = now + (int)x; if(y) ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, r- >server, "Expiry date calculated %ld", (long)expc); }
Can you submit a real patch? Please see http://httpd.apache.org/dev/patches.html
Has this bug been fixed in 2.0.x? Thanks.
(In reply to comment #3) > Has this bug been fixed in 2.0.x? > > Thanks. I'm using 2.2.0 and it appears that the bug hasn't been fixed. Currently I have a setup with CacheMaxExpire 600, but I get answers from my cache with "Age: 2294", so that can't be right. It would appear that cache_util doesn't honour CacheMaxExpire at all. When looking at modules/cache/cache_util.c, around line 298, I see: /* handle expiration */ if (((smaxage != -1) && (age < (smaxage - minfresh))) || ((maxage != -1) && (age < (maxage + maxstale - minfresh))) || ((smaxage == -1) && (maxage == -1) && (info->expire != APR_DATE_BAD) && (age < (apr_time_sec(info->expire - info->date) + maxstale - minfresh)))) { const char *warn_head; warn_head = apr_table_get(h->resp_hdrs, "Warning"); /* it's fresh darlings... */ i.e. nothing relating to CacheMaxExpire The only references to CacheMaxExpire are in mod_cache.c, line 692 where Expires headers are created based on last modified headers.
Created attachment 19344 [details] patch for 2.2.x If conf->maxex is set, and age is greater in seconds, expire the content. "if (conf->maxex != -1)" doesn't seem to be needed, as without CacheMaxExpire defined conf->maxex is 86400 (1 day).
looks like mod_cache
CacheMaxExpire as used in this patch seems to limit the max cache time to a default of 86400 seconds (1 day), which is broken - caches should definitely be allowed to cache for more than a day. Looking at CacheMinExpire, the directive is only valid when an Expires header is not present (as per the docs), and currently, CacheMaxExpire is also only valid when the expires header is missing. Either the docs need to be changed, to reflect this, or the default value of CacheMaxExpire needs to default to no limit.
(In reply to comment #7) > CacheMaxExpire as used in this patch seems to limit the max cache time to a > default of 86400 seconds (1 day), which is broken - caches should definitely be > allowed to cache for more than a day. Both behaviors are probably wanted/needed by different users. For us that have content that _might_ change we can live with a freshness-check once a day in order to have the cache deliver stale content for a day maximum (or whatever you set CacheMaxExpire to). Others might want to have the current code behavior, I personally prefer the documented one. If I remember correctly passing the cache expire triggers a freshness check, and if it's not-modified we're content with the cached body and write a new header. Doing this once a day by default is sane IMHO, no matter what Expires-header is passed by the upper layer.
(In reply to comment #8) > > If I remember correctly passing the cache expire triggers a freshness check, > and if it's not-modified we're content with the cached body and write a new > header. > Doing this once a day by default is sane IMHO, no matter what Expires-header is > passed by the upper layer. But i don't think that's true. Because let's say i have a file with a max-age value of 4 hours and a cachemaxexpire setting with a value of 5 minutes. I've had old file content being served from the cache (i.e. having an Age header > CacheMaxExpire and < max-age) when new file content existed on the FS.
Created attachment 31447 [details] Change CacheMaxExpire/CacheMinExpire doc to be more accurate This behavior is still around today, in trunk. To summarize the discussion: CacheMaxExpire/CacheMinExpire only take effect if no valid expiry date is specified and a valid last modified date is specified. Additionally, they are unconditionally overriden by Cache-Control header directives. One can see this behavior by following the code paths in mod_cache.c (cache_save_filter(), do a search on "maxex") and cache_util.c (cache_check_freshness(), called from cache_select() in cache_storage.c). The documentation, on the other hand, says that CacheMaxExpire overrides the expiry date supplied, and says pretty much nothing as to whether it affects the Cache-Control directives or not. CacheMinExpire says "This is only used if no valid expire time was supplied with the document", which is actually true, but ignores the fact that a valid Last-Modified value must be supplied as well. There's also this confusing case in cache_save_filter(): if there's a max-age and a last-modified date but no valid expiry date, CacheMaxExpire/CacheMinExpire try to do something by setting the expiry date field (what would normally get set by the Expires header). However, that field just gets overriden by max-age anyway in cache_check_freshness(), so nothing is accomplished. This behavior's apparently been around for more than ten years, so I've taken a shot at changing the documentation only. However, I do also feel that these directives are not very useful as they are currently implemented.
Please help us to refine our list of open and current defects; this is a mass update of old and inactive Bugzilla reports which reflect user error, already resolved defects, and still-existing defects in httpd. As repeatedly announced, the Apache HTTP Server Project has discontinued all development and patch review of the 2.2.x series of releases. The final release 2.2.34 was published in July 2017, and no further evaluation of bug reports or security risks will be considered or published for 2.2.x releases. All reports older than 2.4.x have been updated to status RESOLVED/LATER; no further action is expected unless the report still applies to a current version of httpd. If your report represented a question or confusion about how to use an httpd feature, an unexpected server behavior, problems building or installing httpd, or working with an external component (a third party module, browser etc.) we ask you to start by bringing your question to the User Support and Discussion mailing list, see [https://httpd.apache.org/lists.html#http-users] for details. Include a link to this Bugzilla report for completeness with your question. If your report was clearly a defect in httpd or a feature request, we ask that you retest using a modern httpd release (2.4.33 or later) released in the past year. If it can be reproduced, please reopen this bug and change the Version field above to the httpd version you have reconfirmed with. Your help in identifying defects or enhancements still applicable to the current httpd server software release is greatly appreciated.
The doc says "This maximum value is enforced even if an expiry date was supplied with the document." that IS NOT the case, the Expires header for example overwrites the CacheMaxExpire directives (Expires is used).