mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 15:17:01 +02:00
MINOR: cache: Improve accept_encoding_normalizer
Turn the "Accept-Encoding" value to lower case before processing it. Calculate the CRC on every token instead of a sorted concatenation of them all (in order to avoir copying them) then XOR all the CRCs into a single hash (while ignoring duplicates).
This commit is contained in:
parent
f67442efdb
commit
8bb72aa82f
13
reg-tests/cache/vary.vtc
vendored
13
reg-tests/cache/vary.vtc
vendored
@ -187,8 +187,9 @@ client c1 -connect ${h1_fe_sock} {
|
|||||||
expect resp.http.content-type == "text/plain"
|
expect resp.http.content-type == "text/plain"
|
||||||
expect resp.http.X-Cache-Hit == 1
|
expect resp.http.X-Cache-Hit == 1
|
||||||
|
|
||||||
# The accept-encoding normalizer function sorts alphabeticaly the values
|
# The accept-encoding normalizer function converts the header values
|
||||||
# before calculating the secondary key
|
# to lower case then calculates the hash of every sub part before
|
||||||
|
# sorting the hashes and xor'ing them (while removing duplicates).
|
||||||
txreq -url "/accept-encoding-multiple" -hdr "Accept-Encoding: first,second"
|
txreq -url "/accept-encoding-multiple" -hdr "Accept-Encoding: first,second"
|
||||||
rxresp
|
rxresp
|
||||||
expect resp.status == 200
|
expect resp.status == 200
|
||||||
@ -207,6 +208,12 @@ client c1 -connect ${h1_fe_sock} {
|
|||||||
expect resp.bodylen == 51
|
expect resp.bodylen == 51
|
||||||
expect resp.http.X-Cache-Hit == 1
|
expect resp.http.X-Cache-Hit == 1
|
||||||
|
|
||||||
|
txreq -url "/accept-encoding-multiple" -hdr "Accept-Encoding: FirsT,SECOND,first"
|
||||||
|
rxresp
|
||||||
|
expect resp.status == 200
|
||||||
|
expect resp.bodylen == 51
|
||||||
|
expect resp.http.X-Cache-Hit == 1
|
||||||
|
|
||||||
# Unmanaged vary
|
# Unmanaged vary
|
||||||
txreq -url "/unmanaged" -hdr "Accept-Encoding: first_value"
|
txreq -url "/unmanaged" -hdr "Accept-Encoding: first_value"
|
||||||
rxresp
|
rxresp
|
||||||
@ -270,7 +277,7 @@ client c1 -connect ${h1_fe_sock} {
|
|||||||
expect resp.bodylen == 57
|
expect resp.bodylen == 57
|
||||||
expect resp.http.X-Cache-Hit == 1
|
expect resp.http.X-Cache-Hit == 1
|
||||||
|
|
||||||
# The following requests are trated by a backend that does not cache
|
# The following requests are treated by a backend that does not cache
|
||||||
# responses containing a Vary header
|
# responses containing a Vary header
|
||||||
txreq -url "/no_vary_support"
|
txreq -url "/no_vary_support"
|
||||||
rxresp
|
rxresp
|
||||||
|
49
src/cache.c
49
src/cache.c
@ -1791,10 +1791,14 @@ struct flt_ops cache_ops = {
|
|||||||
|
|
||||||
int accept_encoding_cmp(const void *a, const void *b)
|
int accept_encoding_cmp(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
const struct ist ist_a = *(const struct ist*)a;
|
unsigned int int_a = *(unsigned int*)a;
|
||||||
const struct ist ist_b = *(const struct ist*)b;
|
unsigned int int_b = *(unsigned int*)b;
|
||||||
|
|
||||||
return istdiff(ist_a, ist_b);
|
if (int_a < int_b)
|
||||||
|
return -1;
|
||||||
|
if (int_a > int_b)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ACCEPT_ENCODING_MAX_ENTRIES 16
|
#define ACCEPT_ENCODING_MAX_ENTRIES 16
|
||||||
@ -1804,33 +1808,38 @@ int accept_encoding_cmp(const void *a, const void *b)
|
|||||||
* for the newly constructed buffer.
|
* for the newly constructed buffer.
|
||||||
* Returns 0 in case of success.
|
* Returns 0 in case of success.
|
||||||
*/
|
*/
|
||||||
static int accept_encoding_normalizer(struct ist value, char *buf, unsigned int *buf_len)
|
static int accept_encoding_normalizer(struct ist full_value, char *buf, unsigned int *buf_len)
|
||||||
{
|
{
|
||||||
struct ist values[ACCEPT_ENCODING_MAX_ENTRIES] = {{}};
|
unsigned int values[ACCEPT_ENCODING_MAX_ENTRIES] = {};
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
char *comma = NULL;
|
char *comma = NULL;
|
||||||
struct buffer *trash = get_trash_chunk();
|
unsigned int hash_value = 0;
|
||||||
int hash_value = 0;
|
unsigned int prev = 0, curr = 0;
|
||||||
|
|
||||||
|
/* Turn accept-encoding value to lower case */
|
||||||
|
full_value = ist2bin_lc(istptr(full_value), full_value);
|
||||||
|
|
||||||
/* The hash will be built out of a sorted list of accepted encodings. */
|
/* The hash will be built out of a sorted list of accepted encodings. */
|
||||||
while (count < (ACCEPT_ENCODING_MAX_ENTRIES - 1) && (comma = istchr(value, ',')) != NULL) {
|
while (count < (ACCEPT_ENCODING_MAX_ENTRIES - 1) && (comma = istchr(full_value, ',')) != NULL) {
|
||||||
size_t length = comma - istptr(value);
|
size_t length = comma - istptr(full_value);
|
||||||
|
|
||||||
|
values[count++] = hash_crc32(istptr(full_value), length);
|
||||||
|
|
||||||
|
full_value = istadv(full_value, length + 1);
|
||||||
|
|
||||||
values[count++] = isttrim(value, length);
|
|
||||||
value = istadv(value, length + 1);
|
|
||||||
}
|
}
|
||||||
values[count++] = value;
|
values[count++] = hash_crc32(istptr(full_value), istlen(full_value));
|
||||||
|
|
||||||
if (count == ACCEPT_ENCODING_MAX_ENTRIES)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* Sort the values alphabetically. */
|
/* Sort the values alphabetically. */
|
||||||
qsort(values, count, sizeof(struct ist), &accept_encoding_cmp);
|
qsort(values, count, sizeof(*values), &accept_encoding_cmp);
|
||||||
|
|
||||||
while (count)
|
while (count) {
|
||||||
chunk_istcat(trash, values[--count]);
|
curr = values[--count];
|
||||||
|
if (curr != prev) {
|
||||||
hash_value = hash_crc32(b_orig(trash), b_data(trash));
|
hash_value ^= curr;
|
||||||
|
}
|
||||||
|
prev = curr;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(buf, &hash_value, sizeof(hash_value));
|
memcpy(buf, &hash_value, sizeof(hash_value));
|
||||||
*buf_len = sizeof(hash_value);
|
*buf_len = sizeof(hash_value);
|
||||||
|
Loading…
Reference in New Issue
Block a user