MINOR: cache: Do not store responses with an unknown encoding
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.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index d357b89..64b7350 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -14616,6 +14616,9 @@
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
diff --git a/reg-tests/cache/vary_accept_encoding.vtc b/reg-tests/cache/vary_accept_encoding.vtc
index 59e819a..185ad05 100644
--- a/reg-tests/cache/vary_accept_encoding.vtc
+++ b/reg-tests/cache/vary_accept_encoding.vtc
@@ -292,6 +292,7 @@
#
# 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 @@
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
#
diff --git a/src/cache.c b/src/cache.c
index 7f6955a..32c99cd 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -933,8 +933,11 @@
* 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 @@
}
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 @@
/* 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 @@
/* 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)) {