mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-04-25 12:28:01 +00:00
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.
This commit is contained in:
parent
b62b78be13
commit
6ca89162dc
@ -14616,6 +14616,9 @@ The cache won't store and won't deliver objects in these cases:
|
|||||||
headers)
|
headers)
|
||||||
- If the process-vary option is enabled and there are already max-secondary-entries
|
- If the process-vary option is enabled and there are already max-secondary-entries
|
||||||
entries with the same primary key as the current response
|
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 request is not a GET
|
||||||
- If the HTTP version of the request is smaller than 1.1
|
- If the HTTP version of the request is smaller than 1.1
|
||||||
|
9
reg-tests/cache/vary_accept_encoding.vtc
vendored
9
reg-tests/cache/vary_accept_encoding.vtc
vendored
@ -292,6 +292,7 @@ client c1 -connect ${h1_fe_sock} {
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Unknown content-encoding
|
# 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"
|
txreq -url "/unknown-content-encoding" -hdr "Accept-Encoding: gzip;q=0.8, deflate, first_encoding"
|
||||||
rxresp
|
rxresp
|
||||||
@ -305,14 +306,6 @@ client c1 -connect ${h1_fe_sock} {
|
|||||||
expect resp.status == 200
|
expect resp.status == 200
|
||||||
expect resp.http.content-encoding == "unknown_encoding"
|
expect resp.http.content-encoding == "unknown_encoding"
|
||||||
expect resp.bodylen == 119
|
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
|
expect resp.http.X-Cache-Hit == 0
|
||||||
|
|
||||||
#
|
#
|
||||||
|
23
src/cache.c
23
src/cache.c
@ -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
|
* 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,
|
* encoding bitmap part of the hash with the actual encoding of the response,
|
||||||
* extracted from the content-encoding header value.
|
* 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;
|
unsigned int resp_encoding_bitmap = 0;
|
||||||
const struct vary_hashing_information *info = vary_information;
|
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)
|
if (count == hash_info_count)
|
||||||
return;
|
return -1;
|
||||||
|
|
||||||
while (http_find_header(htx, ist("content-encoding"), &ctx, 0)) {
|
while (http_find_header(htx, ist("content-encoding"), &ctx, 0)) {
|
||||||
if (!parse_encoding_value(ctx.value, &encoding_value, NULL))
|
if (parse_encoding_value(ctx.value, &encoding_value, NULL))
|
||||||
resp_encoding_bitmap |= encoding_value;
|
return -1; /* Do not store responses with an unknown encoding */
|
||||||
else
|
resp_encoding_bitmap |= encoding_value;
|
||||||
resp_encoding_bitmap |= VARY_ENCODING_OTHER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resp_encoding_bitmap)
|
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
|
/* Rewrite the bitmap part of the hash with the new bitmap that only
|
||||||
* corresponds the the response's encoding. */
|
* corresponds the the response's encoding. */
|
||||||
write_u32(secondary_key + offset, resp_encoding_bitmap);
|
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
|
/* If the response has a secondary_key, fill its key part related to
|
||||||
* encodings with the actual encoding of the response. This way any
|
* encodings with the actual encoding of the response. This way any
|
||||||
* subsequent request having the same primary key will have its accepted
|
* 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)
|
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);
|
shctx_lock(shctx);
|
||||||
if (!shctx_row_reserve_hot(shctx, first, trash.data)) {
|
if (!shctx_row_reserve_hot(shctx, first, trash.data)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user