MINOR: cache: Do not store stale entry
When a response has an Age header (filled in by another cache on the
message's path) that is greater than its defined maximum age (extracted
either from cache-control directives or an expires header), it is
already stale and should not be cached.
diff --git a/src/cache.c b/src/cache.c
index 420a009..cc44650 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -535,6 +535,10 @@
/*
* Return the maxage in seconds of an HTTP response.
+ * The returned value will always take the cache's configuration into account
+ * (cache->maxage) but the actual max age of the response will be set in the
+ * true_maxage parameter. It will be used to determine if a response is already
+ * stale or not.
* Compute the maxage using either:
* - the assigned max-age of the cache
* - the s-maxage directive
@@ -543,7 +547,7 @@
* - the default-max-age of the cache
*
*/
-int http_calc_maxage(struct stream *s, struct cache *cache)
+int http_calc_maxage(struct stream *s, struct cache *cache, int *true_maxage)
{
struct htx *htx = htxbuf(&s->res.buf);
struct http_hdr_ctx ctx = { .blk = NULL };
@@ -599,14 +603,23 @@
}
- if (smaxage > 0)
+ if (smaxage > 0) {
+ if (true_maxage)
+ *true_maxage = smaxage;
return MIN(smaxage, cache->maxage);
+ }
- if (maxage > 0)
+ if (maxage > 0) {
+ if (true_maxage)
+ *true_maxage = maxage;
return MIN(maxage, cache->maxage);
+ }
- if (expires >= 0)
+ if (expires >= 0) {
+ if (true_maxage)
+ *true_maxage = expires;
return MIN(expires, cache->maxage);
+ }
return cache->maxage;
@@ -698,6 +711,8 @@
struct session *sess, struct stream *s, int flags)
{
long long hdr_age;
+ int effective_maxage = 0;
+ int true_maxage = 0;
struct http_txn *txn = s->txn;
struct http_msg *msg = &txn->rsp;
struct filter *filter;
@@ -828,12 +843,21 @@
first->len = sizeof(struct cache_entry);
first->last_append = NULL;
+ /* Determine the entry's maximum age (taking into account the cache's
+ * configuration) as well as the response's explicit max age (extracted
+ * from cache-control directives or the expires header). */
+ effective_maxage = http_calc_maxage(s, cconf->c.cache, &true_maxage);
+
ctx.blk = NULL;
if (http_find_header(htx, ist("Age"), &ctx, 0)) {
if (!strl2llrc(ctx.value.ptr, ctx.value.len, &hdr_age) && hdr_age > 0) {
if (unlikely(hdr_age > CACHE_ENTRY_MAX_AGE))
hdr_age = CACHE_ENTRY_MAX_AGE;
+ /* A response with an Age value greater than its
+ * announced max age is stale and should not be stored. */
object->age = hdr_age;
+ if (unlikely(object->age > true_maxage))
+ goto out;
}
http_remove_header(htx, &ctx);
}
@@ -894,8 +918,7 @@
/* store latest value and expiration time */
object->latest_validation = now.tv_sec;
- object->expire = now.tv_sec + http_calc_maxage(s, cache);
-
+ object->expire = now.tv_sec + effective_maxage;
return ACT_RET_CONT;
}