diff --git a/reg-tests/cache/vary.vtc b/reg-tests/cache/vary.vtc index 61d7af671..197f822b3 100644 --- a/reg-tests/cache/vary.vtc +++ b/reg-tests/cache/vary.vtc @@ -108,7 +108,18 @@ server s1 { -hdr "Content-Encoding: gzip" \ -bodylen 188 + rxreq + expect req.url == "/empty-vs-missing" + txresp -hdr "Content-Encoding: gzip" \ + -hdr "Vary: accept-encoding" \ + -hdr "Cache-Control: max-age=5" \ + -bodylen 234 + rxreq + expect req.url == "/empty-vs-missing" + txresp -hdr "Vary: accept-encoding" \ + -hdr "Cache-Control: max-age=5" \ + -bodylen 256 } -start server s2 { @@ -344,6 +355,42 @@ client c1 -connect ${h1_fe_sock} { expect resp.bodylen == 188 expect resp.http.X-Cache-Hit == 0 + # A missing 'Accept-Encoding' implies that anything is acceptable, + # while an empty 'Accept-Encoding' implies nothing is acceptable. + + # Start by caching a gzip response. + txreq -url "/empty-vs-missing" -hdr "Accept-Encoding: gzip" + rxresp + expect resp.status == 200 + expect resp.bodylen == 234 + expect resp.http.content-encoding == "gzip" + expect resp.http.X-Cache-Hit == 0 + + # Check that it is cached. + txreq -url "/empty-vs-missing" -hdr "Accept-Encoding: gzip" + rxresp + expect resp.status == 200 + expect resp.bodylen == 234 + expect resp.http.content-encoding == "gzip" + expect resp.http.X-Cache-Hit == 1 + + # Check that the cached response is returned when no accept-encoding is + # specified. + txreq -url "/empty-vs-missing" + rxresp + expect resp.status == 200 + expect resp.bodylen == 234 + expect resp.http.content-encoding == "gzip" + expect resp.http.X-Cache-Hit == 1 + + # Check that the cached response is not returned when an empty + # accept-encoding is specified. + txreq -url "/empty-vs-missing" -hdr "Accept-Encoding:" + rxresp + expect resp.status == 200 + expect resp.bodylen == 256 + expect resp.http.content-encoding == "" + expect resp.http.X-Cache-Hit == 0 # The following requests are treated by a backend that does not cache # responses containing a Vary header diff --git a/src/cache.c b/src/cache.c index bdb82583f..feab63f07 100644 --- a/src/cache.c +++ b/src/cache.c @@ -2280,6 +2280,19 @@ static int accept_encoding_normalizer(struct htx *htx, struct ist hdr_name, /* Iterate over all the ACCEPT_ENCODING_MAX_ENTRIES first accept-encoding * values that might span acrosse multiple accept-encoding headers. */ while (http_find_header(htx, hdr_name, &ctx, 0) && count < ACCEPT_ENCODING_MAX_ENTRIES) { + count++; + + /* As per RFC7231#5.3.4, "An Accept-Encoding header field with a + * combined field-value that is empty implies that the user agent + * does not want any content-coding in response." + * + * We must (and did) count the existence of this empty header to not + * hit the `count == 0` case below, but must ignore the value to not + * include VARY_ENCODING_OTHER into the final bitmap. + */ + if (istlen(ctx.value) == 0) + continue; + /* Turn accept-encoding value to lower case */ ist2bin_lc(istptr(ctx.value), ctx.value); @@ -2294,8 +2307,6 @@ static int accept_encoding_normalizer(struct htx *htx, struct ist hdr_name, /* Unknown encoding */ encoding_bitmap |= VARY_ENCODING_OTHER; } - - count++; } /* If a "*" was found in the accepted encodings (without a null weight),