]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: cache: Add "Origin" header to secondary cache key
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Tue, 3 Oct 2023 12:33:41 +0000 (14:33 +0200)
committerWilliam Lallemand <wlallemand@haproxy.com>
Thu, 5 Oct 2023 08:53:54 +0000 (10:53 +0200)
This patch add a hash of the Origin header to the cache's secondary key.
This enables to manage store responses that have a "Vary: Origin" header
in the cache when vary is enabled.
This cannot be considered as a means to manage CORS requests though, it
only processes the Origin header and hashes the presented value without
any form of URI normalization.

This need was expressed by Philipp Hossner in GitHub issue #251.

Co-Authored-by: Philipp Hossner <philipp.hossner@posteo.de>
doc/configuration.txt
include/haproxy/http_ana-t.h
reg-tests/cache/vary.vtc
src/cache.c

index cd15e93aa2d4d1f23540dc41ef412518923b35e2..dd78f454264a4f7176fda60965aa0420e2606109 100644 (file)
@@ -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 <on/off>
   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 <number>
   Define the maximum number of simultaneous secondary entries with the same primary
index 39ec989946a1e30236182bdb3e36baeeda6fa4f2..6d8022aa2da531971c78674fd85a17ad1889a367 100644 (file)
@@ -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 */
index b1c1bda9cf13647b855d31c47a4d28f226db3aff..6c8cedf337aa21827d72fcd630a10828e8dccd29 100644 (file)
@@ -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" \
index b9fd47e7ba64dc01b3dda50504303c1bd87f18c1..eab3f975200e6c88037e133903d85905716a6b96 100644 (file)
@@ -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.