]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cache: Do not store responses with an unknown encoding
authorRemi Tricot-Le Breton <rlebreton@haproxy.com>
Thu, 7 Jan 2021 13:50:51 +0000 (14:50 +0100)
committerWilliam Lallemand <wlallemand@haproxy.org>
Fri, 15 Jan 2021 21:33:05 +0000 (22:33 +0100)
If a server varies on the accept-encoding header and it sends a response
with an encoding we do not know (see parse_encoding_value function), we
will not store it. This will prevent unexpected errors caused by
cache collisions that could happen in accept_encoding_hash_cmp.

doc/configuration.txt
reg-tests/cache/vary_accept_encoding.vtc
src/cache.c

index d357b89c29083d7fc697979eb7c6442f611745b4..64b73501d22ca56760d3d4a73f7fe2ee37891a27 100644 (file)
@@ -14616,6 +14616,9 @@ The cache won't store and won't deliver objects in these cases:
   headers)
 - If the process-vary option is enabled and there are already max-secondary-entries
   entries with the same primary key as the current response
+- If the process-vary option is enabled and the response has an unknown encoding (not
+  mentioned in https://www.iana.org/assignments/http-parameters/http-parameters.xhtml)
+  while varying on the accept-encoding client header
 
 - If the request is not a GET
 - If the HTTP version of the request is smaller than 1.1
index 59e819a7585f731c93b71ab5a827bd4351d1e7ec..185ad0502bf003dd2d006f5f975de01425f35216 100644 (file)
@@ -292,6 +292,7 @@ client c1 -connect ${h1_fe_sock} {
 
        #
        # Unknown content-encoding
+       # The response should not be cached since it has an unknown content encoding
        #
        txreq -url "/unknown-content-encoding" -hdr "Accept-Encoding: gzip;q=0.8, deflate, first_encoding"
        rxresp
@@ -305,14 +306,6 @@ client c1 -connect ${h1_fe_sock} {
        expect resp.status == 200
        expect resp.http.content-encoding == "unknown_encoding"
        expect resp.bodylen == 119
-       expect resp.http.X-Cache-Hit == 1
-
-       # Different set of accepted encodings
-       txreq -url "/unknown-content-encoding" -hdr "Accept-Encoding: deflate, first_encoding"
-       rxresp
-       expect resp.status == 200
-       expect resp.http.content-encoding == "unknown_encoding"
-       expect resp.bodylen == 119
        expect resp.http.X-Cache-Hit == 0
 
        #
index 7f6955afcfa28f0fc8c68568185bf856e5e56f56..32c99cdc4aaedb08f301de0a10839acb9bf64806 100644 (file)
@@ -933,8 +933,11 @@ static int http_check_vary_header(struct htx *htx, unsigned int *vary_signature)
  * Look for the accept-encoding part of the secondary_key and replace the
  * encoding bitmap part of the hash with the actual encoding of the response,
  * extracted from the content-encoding header value.
+ * Responses that have an unknown encoding will not be cached if they also
+ * "vary" on the accept-encoding value.
+ * Returns 0 if we found a known encoding in the response, -1 otherwise.
  */
-static void set_secondary_key_encoding(struct htx *htx, char *secondary_key)
+static int set_secondary_key_encoding(struct htx *htx, char *secondary_key)
 {
        unsigned int resp_encoding_bitmap = 0;
        const struct vary_hashing_information *info = vary_information;
@@ -952,13 +955,12 @@ static void set_secondary_key_encoding(struct htx *htx, char *secondary_key)
        }
 
        if (count == hash_info_count)
-               return;
+               return -1;
 
        while (http_find_header(htx, ist("content-encoding"), &ctx, 0)) {
-               if (!parse_encoding_value(ctx.value, &encoding_value, NULL))
-                       resp_encoding_bitmap |= encoding_value;
-               else
-                       resp_encoding_bitmap |= VARY_ENCODING_OTHER;
+               if (parse_encoding_value(ctx.value, &encoding_value, NULL))
+                       return -1; /* Do not store responses with an unknown encoding */
+               resp_encoding_bitmap |= encoding_value;
        }
 
        if (!resp_encoding_bitmap)
@@ -967,6 +969,8 @@ static void set_secondary_key_encoding(struct htx *htx, char *secondary_key)
        /* Rewrite the bitmap part of the hash with the new bitmap that only
         * corresponds the the response's encoding. */
        write_u32(secondary_key + offset, resp_encoding_bitmap);
+
+       return 0;
 }
 
 
@@ -1197,9 +1201,12 @@ enum act_return http_action_store_cache(struct act_rule *rule, struct proxy *px,
        /* If the response has a secondary_key, fill its key part related to
         * encodings with the actual encoding of the response. This way any
         * subsequent request having the same primary key will have its accepted
-        * encodings tested upon the cached response's one. */
+        * encodings tested upon the cached response's one.
+        * We will not cache a response that has an unknown encoding (not
+        * explicitely supported in parse_encoding_value function). */
        if (cache->vary_processing_enabled && vary_signature)
-               set_secondary_key_encoding(htx, object->secondary_key);
+               if (set_secondary_key_encoding(htx, object->secondary_key))
+                   goto out;
 
        shctx_lock(shctx);
        if (!shctx_row_reserve_hot(shctx, first, trash.data)) {