MEDIUM: cache: Change caching conditions

Do not cache responses that do not have an explicit expiration time
(s-maxage or max-age Cache-Control directives or Expires header) or a
validator (ETag or Last-Modified headers) anymore, as suggested in
RFC 7234#3.
The TX_FLAG_IGNORE flag is used instead of the TX_FLAG_CACHEABLE so as
not to change the behavior of the checkcache option.

(cherry picked from commit cc9bf2e5fe1fe6f15de9e78b6aaea2cd6be5ca4f)
Signed-off-by: William Lallemand <wlallemand@haproxy.org>
diff --git a/src/cache.c b/src/cache.c
index f86c96f..4f8fad9 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -664,7 +664,7 @@
 
 	http_check_response_for_cacheability(s, &s->res);
 
-	if (!(txn->flags & TX_CACHEABLE) || !(txn->flags & TX_CACHE_COOK))
+	if (!(txn->flags & TX_CACHEABLE) || !(txn->flags & TX_CACHE_COOK) || (txn->flags & TX_CACHE_IGNORE))
 		goto out;
 
 	age = 0;
diff --git a/src/http_ana.c b/src/http_ana.c
index deec220..7a9cd0b 100644
--- a/src/http_ana.c
+++ b/src/http_ana.c
@@ -3916,6 +3916,8 @@
 	struct http_txn *txn = s->txn;
 	struct http_hdr_ctx ctx = { .blk = NULL };
 	struct htx *htx;
+	int has_freshness_info = 0;
+	int has_validator = 0;
 
 	if (txn->status < 200) {
 		/* do not try to cache interim responses! */
@@ -3953,7 +3955,37 @@
 			txn->flags &= ~TX_CACHE_COOK;
 			continue;
 		}
+
+		if (istmatchi(ctx.value, ist("s-maxage")) ||
+		    istmatchi(ctx.value, ist("max-age"))) {
+			has_freshness_info = 1;
+			continue;
+		}
+	}
+
+	/* If no freshness information could be found in Cache-Control values,
+	 * look for an Expires header. */
+	if (!has_freshness_info) {
+		ctx.blk = NULL;
+		has_freshness_info = http_find_header(htx, ist("expires"), &ctx, 0);
 	}
+
+	/* If no freshness information could be found in Cache-Control or Expires
+	 * values, look for an explicit validator. */
+	if (!has_freshness_info) {
+		ctx.blk = NULL;
+		has_validator = 1;
+		if (!http_find_header(htx, ist("etag"), &ctx, 0)) {
+			ctx.blk = NULL;
+			if (!http_find_header(htx, ist("last-modified"), &ctx, 0))
+				has_validator = 0;
+		}
+	}
+
+	/* We won't store an entry that has neither a cache validator nor an
+	 * explicit expiration time, as suggested in RFC 7234#3. */
+	if (!has_freshness_info && !has_validator)
+		txn->flags |= TX_CACHE_IGNORE;
 }
 
 /*