diff --git a/doc/configuration.txt b/doc/configuration.txt index cd15e93aa..dd78f4542 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -17178,7 +17178,7 @@ The cache won't store and won't deliver objects in these cases: - If the response is not a 200 - If the response contains a Vary header and either the process-vary option is disabled, or a currently unmanaged header is specified in the Vary value (only - accept-encoding and referer are managed for now) + accept-encoding, referer and origin are managed for now) - If the Content-Length + the headers size is greater than "max-object-size" - If the response is not cacheable - If the response does not have an explicit expiration time (s-maxage or max-age @@ -17229,8 +17229,10 @@ process-vary Enable or disable the processing of the Vary header. When disabled, a response containing such a header will never be cached. When enabled, we need to calculate a preliminary hash for a subset of request headers on all the incoming requests - (which might come with a cpu cost) which will be used to build a secondary key - for a given request (see RFC 7234#4.1). The default value is off (disabled). + (which might come with a cpu cost) which will be used to build a secondary + key for a given request (see RFC 7234#4.1). The secondary key is built out of + the contents of the 'accept-encoding', 'referer' and 'origin' headers for + now. The default value is off (disabled). max-secondary-entries Define the maximum number of simultaneous secondary entries with the same primary diff --git a/include/haproxy/http_ana-t.h b/include/haproxy/http_ana-t.h index 39ec98994..6d8022aa2 100644 --- a/include/haproxy/http_ana-t.h +++ b/include/haproxy/http_ana-t.h @@ -157,7 +157,7 @@ static forceinline char *hmsg_show_flags(char *buf, size_t len, const char *deli * request/response pairs, because they depend on the responses' optional Vary * header. The different sizes can be found in the vary_information object (see * cache.c).*/ -#define HTTP_CACHE_SEC_KEY_LEN (sizeof(uint32_t)+sizeof(uint64_t)) +#define HTTP_CACHE_SEC_KEY_LEN (sizeof(uint32_t)+sizeof(uint64_t)+sizeof(uint64_t)) /* Redirect flags */ diff --git a/reg-tests/cache/vary.vtc b/reg-tests/cache/vary.vtc index b1c1bda9c..6c8cedf33 100644 --- a/reg-tests/cache/vary.vtc +++ b/reg-tests/cache/vary.vtc @@ -77,6 +77,20 @@ server s1 { -hdr "Content-Encoding: gzip" \ -bodylen 57 + rxreq + expect req.url == "/origin-referer-accept-encoding" + txresp -hdr "Vary: origin,referer,accept-encoding" \ + -hdr "Cache-Control: max-age=5" \ + -hdr "Content-Encoding: gzip" \ + -bodylen 58 + + rxreq + expect req.url == "/origin-referer-accept-encoding" + txresp -hdr "Vary: origin,referer,accept-encoding" \ + -hdr "Cache-Control: max-age=5" \ + -hdr "Content-Encoding: gzip" \ + -bodylen 59 + # Multiple Accept-Encoding headers rxreq expect req.url == "/multiple_headers" @@ -315,6 +329,43 @@ client c1 -connect ${h1_fe_sock} { expect resp.http.X-Cache-Hit == 1 + # Mixed Vary (Accept-Encoding + Referer + Origin) + txreq -url "/origin-referer-accept-encoding" \ + -hdr "Accept-Encoding: br, gzip" \ + -hdr "Referer: referer" \ + -hdr "Origin: origin" + rxresp + expect resp.status == 200 + expect resp.bodylen == 58 + expect resp.http.X-Cache-Hit == 0 + + txreq -url "/origin-referer-accept-encoding" \ + -hdr "Accept-Encoding: br, gzip" \ + -hdr "Referer: referer" \ + -hdr "Origin: origin" + rxresp + expect resp.status == 200 + expect resp.bodylen == 58 + expect resp.http.X-Cache-Hit == 1 + + txreq -url "/origin-referer-accept-encoding" \ + -hdr "Accept-Encoding: br, gzip" \ + -hdr "Referer: referer" \ + -hdr "Origin: other-origin" + rxresp + expect resp.status == 200 + expect resp.bodylen == 59 + expect resp.http.X-Cache-Hit == 0 + + txreq -url "/origin-referer-accept-encoding" \ + -hdr "Accept-Encoding: br, gzip" \ + -hdr "Referer: referer" \ + -hdr "Origin: other-origin" + rxresp + expect resp.status == 200 + expect resp.bodylen == 59 + expect resp.http.X-Cache-Hit == 1 + # Multiple Accept-encoding headers txreq -url "/multiple_headers" \ -hdr "Accept-Encoding: gzip" \ diff --git a/src/cache.c b/src/cache.c index b9fd47e7b..eab3f9752 100644 --- a/src/cache.c +++ b/src/cache.c @@ -93,6 +93,7 @@ struct show_cache_ctx { enum vary_header_bit { VARY_ACCEPT_ENCODING = (1 << 0), VARY_REFERER = (1 << 1), + VARY_ORIGIN = (1 << 2), VARY_LAST /* should always be last */ }; @@ -143,6 +144,7 @@ static int accept_encoding_bitmap_cmp(const void *ref, const void *new, unsigned const struct vary_hashing_information vary_information[] = { { IST("accept-encoding"), VARY_ACCEPT_ENCODING, sizeof(uint32_t), &accept_encoding_normalizer, &accept_encoding_bitmap_cmp }, { IST("referer"), VARY_REFERER, sizeof(uint64_t), &default_normalizer, NULL }, + { IST("origin"), VARY_ORIGIN, sizeof(uint64_t), &default_normalizer, NULL }, }; @@ -2370,7 +2372,7 @@ static int accept_encoding_normalizer(struct htx *htx, struct ist hdr_name, #undef ACCEPT_ENCODING_MAX_ENTRIES /* - * Normalizer used by default for the Referer header. It only + * Normalizer used by default for the Referer and Origin header. It only * calculates a hash of the whole value using xxhash algorithm. * Only the first occurrence of the header will be taken into account in the * hash.