From 73472025f2ffd55595e0c1f3dfc600cecb57fbbd Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Sun, 24 May 2026 21:52:54 +0200 Subject: [PATCH] BUG/MINOR: cache: also recognize directives in the form "token=" The caching RFC (9111, but was present since 2616) indicate that cache-control supports both the "token" and "token=..." forms and that consumers are supposed to recognize both. In addition, "private=..." is explicitly mentioned, so servers could very well emit it. However, haproxy only recognizes the short form without argument, except for "no-cache" where it also supports it followed by the beginning of a set-cookie argument. Thus it could miss "private=" or "no-store=". Let's refine the checks. Now we explicitly recognize the form no-cache="set-cookie", and all variants of "token" or "token=" as identical to disable caching. It will more reliably catch such edge cases and make sure we never cache a response marked like this. This should be backported, at least to the latest LTS (3.2), maybe further after some observation. --- src/http_ana.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/http_ana.c b/src/http_ana.c index c687b57d9..d2c2d9c1b 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -3996,19 +3996,19 @@ void http_check_response_for_cacheability(struct stream *s, struct channel *res) continue; } - if (isteqi(ctx.value, ist("private")) || - isteqi(ctx.value, ist("no-cache")) || - isteqi(ctx.value, ist("no-store")) || - isteqi(ctx.value, ist("s-maxage=0"))) { - txn->flags &= ~TX_CACHEABLE & ~TX_CACHE_COOK; - continue; - } /* We might have a no-cache="set-cookie" form. */ - if (istmatchi(ctx.value, ist("no-cache=\"set-cookie"))) { + if (isteqi(ctx.value, ist("no-cache=\"set-cookie\""))) { txn->flags &= ~TX_CACHE_COOK; continue; } + if (isteqi(ctx.value, ist("private")) || istmatchi(ctx.value, ist("private=")) || + isteqi(ctx.value, ist("no-cache")) || istmatchi(ctx.value, ist("no-cache=")) || + isteqi(ctx.value, ist("no-store")) || istmatchi(ctx.value, ist("no-store=")) || + isteqi(ctx.value, ist("s-maxage=0"))) { + txn->flags &= ~TX_CACHEABLE & ~TX_CACHE_COOK; + continue; + } if (istmatchi(ctx.value, ist("s-maxage"))) { has_freshness_info = 1; has_null_maxage = 0; /* The null max-age is overridden, ignore it */