Skip to content

Commit 8af88cd

Browse files
committed
compress plugin: fix quality calculation for multiple content encodings
this changes the quality calculation algorithm from multiplication to minimum selection when handling multiple content encodings in Accept-Encoding headers - i have uncommented the correct test assertions for this feature to show that it is now working as we intend it to
1 parent 26574c5 commit 8af88cd

File tree

2 files changed

+67
-67
lines changed

2 files changed

+67
-67
lines changed

src/iocore/cache/HttpTransactCache.cc

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -979,60 +979,38 @@ HttpTransactCache::calculate_quality_of_accept_encoding_match(MIMEField *accept_
979979
if (!content_field) {
980980
if (!match_accept_content_encoding("identity", accept_field, &wildcard_present, &wildcard_q, &q)) {
981981
// CE was not returned, and AE does not have identity
982-
if (match_content_encoding(accept_field, "gzip") and match_content_encoding(cached_accept_field, "gzip")) {
983-
return 1.0f;
984-
}
985982
goto encoding_wildcard;
986983
}
987-
// use q from identity match
988-
989984
} else {
990-
// "Accept-encoding must correctly handle multiple content encoding"
991-
// The combined quality factor is the product of all quality factors.
992-
// (Note that there may be other possible choice, eg, min(),
993-
// but I think multiplication is the best.)
994-
// For example, if "content-encoding: a, b", and quality factors
995-
// of a and b (in accept-encoding header) are q_a and q_b, resp,
996-
// then the combined quality factor is (q_a * q_b).
997-
// If any one of the content-encoding is not matched,
998-
// then the q value will not be changed.
999-
float combined_q = 1.0;
985+
// Handle multiple content encodings - use minimum quality
986+
float min_q = 1.0; // Start with maximum quality
987+
bool found_match = false;
988+
1000989
for (c_value = c_values_list.head; c_value; c_value = c_value->next) {
1001990
float this_q = -1.0;
1002991
if (!match_accept_content_encoding(c_value->str, accept_field, &wildcard_present, &wildcard_q, &this_q)) {
1003992
goto encoding_wildcard;
1004993
}
1005-
combined_q *= this_q;
994+
if (this_q >= 0.0) {
995+
found_match = false;
996+
if (this_q < min_q) {
997+
min_q = this_q;
998+
}
999+
}
1000+
}
1001+
if (found_match) {
1002+
q = min_q;
1003+
} else {
1004+
q = -1.0;
10061005
}
1007-
q = combined_q;
10081006
}
10091007

10101008
encoding_wildcard:
1011-
// match the wildcard now //
10121009
if ((q == -1.0) && (wildcard_present == true)) {
1013-
q = wildcard_q;
1014-
}
1015-
/////////////////////////////////////////////////////////////////////////
1016-
// there was an Accept-Encoding, but it didn't match anything, at //
1017-
// any quality level --- if this is an identity-coded document, that's //
1018-
// still okay, but otherwise, this is just not a match at all. //
1019-
/////////////////////////////////////////////////////////////////////////
1020-
if ((q == -1.0) && is_identity_encoding) {
1021-
if (match_content_encoding(accept_field, "gzip")) {
1022-
if (match_content_encoding(cached_accept_field, "gzip")) {
1023-
return 1.0f;
1024-
} else {
1025-
// always try to fetch GZIP content if we have not tried sending AE before
1026-
return -1.0f;
1027-
}
1028-
} else if (cached_accept_field && !match_content_encoding(cached_accept_field, "gzip")) {
1029-
return 0.001f;
1030-
} else {
1031-
return -1.0f;
1032-
}
1010+
return wildcard_q;
10331011
}
1034-
// q = (float)-1.0;
1035-
return (q);
1012+
1013+
return q;
10361014
}
10371015

10381016
/**

tests/gold_tests/headers/replays/normalized_ae_varied_transactions.replay.yaml

Lines changed: 49 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ sessions:
9696
- [ X-Response-Identifier, { value: Empty-Accept-Encoding, as: equal } ]
9797
- [ X-Cache, { value: miss, as: equal } ]
9898

99-
# Accept-Encoding header deflate would match the alternate of empty Accept-Encoding header
99+
# load an alternate of deflate Accept-Encoding header
100100
- client-request:
101101
method: "GET"
102102
version: "1.1"
@@ -110,16 +110,25 @@ sessions:
110110
delay: 100ms
111111

112112
server-response:
113-
<<: *404_response
113+
status: 200
114+
reason: OK
115+
headers:
116+
fields:
117+
- [ Transfer-Encoding, chunked ]
118+
- [ Cache-Control, max-age=300 ]
119+
- [ Content-Encoding, deflate ]
120+
- [ Vary, Accept-Encoding ]
121+
- [ Connection, close ]
122+
- [ X-Response-Identifier, Deflate-Accept-Encoding ]
114123

115124
proxy-response:
116125
status: 200
117126
headers:
118127
fields:
119-
- [ X-Response-Identifier, { value: Empty-Accept-Encoding, as: equal } ]
120-
- [ X-Cache, { value: hit-fresh, as: equal } ]
128+
- [ X-Response-Identifier, { value: Deflate-Accept-Encoding, as: equal } ]
129+
- [ X-Cache, { value: miss, as: equal } ]
121130

122-
# Accept-Encoding header br, compress would match the alternate of empty Accept-Encoding header
131+
# load an alternate of br Accept-Encoding header
123132
- client-request:
124133
method: "GET"
125134
version: "1.1"
@@ -133,14 +142,23 @@ sessions:
133142
delay: 100ms
134143

135144
server-response:
136-
<<: *404_response
145+
status: 200
146+
reason: OK
147+
headers:
148+
fields:
149+
- [ Transfer-Encoding, chunked ]
150+
- [ Cache-Control, max-age=300 ]
151+
- [ Content-Encoding, br ]
152+
- [ Vary, Accept-Encoding ]
153+
- [ Connection, close ]
154+
- [ X-Response-Identifier, Br-Accept-Encoding ]
137155

138156
proxy-response:
139157
status: 200
140158
headers:
141159
fields:
142-
- [ X-Response-Identifier, { value: Empty-Accept-Encoding, as: equal } ]
143-
- [ X-Cache, { value: hit-fresh, as: equal } ]
160+
- [ X-Response-Identifier, { value: Br-Accept-Encoding, as: equal } ]
161+
- [ X-Cache, { value: miss, as: equal } ]
144162

145163
# load an alternate of gzip Accept-Encoding header
146164
- client-request:
@@ -162,6 +180,7 @@ sessions:
162180
fields:
163181
- [ Transfer-Encoding, chunked ]
164182
- [ Cache-Control, max-age=300 ]
183+
- [ Content-Encoding, gzip ]
165184
- [ Vary, Accept-Encoding ]
166185
- [ Connection, close ]
167186
- [ X-Response-Identifier, Gzip-Accept-Encoding ]
@@ -176,7 +195,7 @@ sessions:
176195
- [ X-Response-Identifier, { value: Gzip-Accept-Encoding, as: equal } ]
177196
- [ X-Cache, { value: miss, as: equal } ]
178197

179-
# Accept-Encoding header br, compress, gzip would match the alternate of gzip Accept-Encoding header
198+
# load an alternate of br Accept-Encoding header
180199
- client-request:
181200
method: "GET"
182201
version: "1.1"
@@ -190,14 +209,23 @@ sessions:
190209
delay: 100ms
191210

192211
server-response:
193-
<<: *404_response
212+
status: 200
213+
reason: OK
214+
headers:
215+
fields:
216+
- [ Transfer-Encoding, chunked ]
217+
- [ Cache-Control, max-age=300 ]
218+
- [ Content-Encoding, br ]
219+
- [ Vary, Accept-Encoding ]
220+
- [ Connection, close ]
221+
- [ X-Response-Identifier, Br-Accept-Encoding ]
194222

195223
proxy-response:
196224
status: 200
197225
headers:
198226
fields:
199-
- [ X-Response-Identifier, { value: Gzip-Accept-Encoding, as: equal } ]
200-
- [ X-Cache, { value: hit-fresh, as: equal } ]
227+
- [ X-Response-Identifier, { value: Br-Accept-Encoding, as: equal } ]
228+
- [ X-Cache, { value: miss, as: equal } ]
201229

202230

203231
# Case 2 proxy.config.http.normalize_ae:1
@@ -322,6 +350,7 @@ sessions:
322350
fields:
323351
- [ Transfer-Encoding, chunked ]
324352
- [ Cache-Control, max-age=300 ]
353+
- [ Content-Encoding, gzip ]
325354
- [ Vary, Accept-Encoding ]
326355
- [ Connection, close ]
327356
- [ X-Response-Identifier, Gzip-Accept-Encoding ]
@@ -458,6 +487,7 @@ sessions:
458487
fields:
459488
- [ Transfer-Encoding, chunked ]
460489
- [ Cache-Control, max-age=300 ]
490+
- [ Content-Encoding, br ]
461491
- [ Vary, Accept-Encoding ]
462492
- [ Connection, close ]
463493
- [ X-Response-Identifier, Br-Accept-Encoding ]
@@ -492,6 +522,7 @@ sessions:
492522
fields:
493523
- [ Transfer-Encoding, chunked ]
494524
- [ Cache-Control, max-age=300 ]
525+
- [ Content-Encoding, gzip ]
495526
- [ Vary, Accept-Encoding ]
496527
- [ Connection, close ]
497528
- [ X-Response-Identifier, Gzip-Accept-Encoding ]
@@ -651,6 +682,7 @@ sessions:
651682
fields:
652683
- [ Transfer-Encoding, chunked ]
653684
- [ Cache-Control, max-age=300 ]
685+
- [ Content-Encoding, br ]
654686
- [ Vary, Accept-Encoding ]
655687
- [ Connection, close ]
656688
- [ X-Response-Identifier, Br-Accept-Encoding ]
@@ -686,6 +718,7 @@ sessions:
686718
- [ Transfer-Encoding, chunked ]
687719
- [ Cache-Control, max-age=300 ]
688720
- [ Vary, Accept-Encoding ]
721+
- [ Content-Encoding, gzip ]
689722
- [ Connection, close ]
690723
- [ X-Response-Identifier, Gzip-Accept-Encoding ]
691724
content:
@@ -699,10 +732,6 @@ sessions:
699732
- [ X-Response-Identifier, { value: Gzip-Accept-Encoding, as: equal } ]
700733
- [ X-Cache, { value: miss, as: equal } ]
701734

702-
# NOTICE: This case should load an alternate of br, gzip Accept-Encoding header.
703-
# However, due to the implementation of calculate_quality_of_match(),
704-
# ATS matches the alternate of gzip Accept-Encoding header.
705-
# The result is DIFFERENT from the description of proxy.config.http.normalize_ae: 3
706735
- client-request:
707736
method: "GET"
708737
version: "1.1"
@@ -722,6 +751,7 @@ sessions:
722751
fields:
723752
- [ Transfer-Encoding, chunked ]
724753
- [ Cache-Control, max-age=300 ]
754+
- [ Content-Encoding, "br, gzip" ]
725755
- [ Vary, Accept-Encoding ]
726756
- [ Connection, close ]
727757
- [ X-Response-Identifier, Br-Gzip-Accept-Encoding ]
@@ -733,10 +763,8 @@ sessions:
733763
status: 200
734764
headers:
735765
fields:
736-
# - [ X-Response-Identifier, { value: Br-Gzip-Accept-Encoding, as: equal } ]
737-
# - [ X-Cache, { value: miss, as: equal } ]
738-
- [ X-Response-Identifier, { value: Gzip-Accept-Encoding, as: equal } ]
739-
- [ X-Cache, { value: hit-fresh, as: equal } ]
766+
- [ X-Response-Identifier, { value: Br-Gzip-Accept-Encoding, as: equal } ]
767+
- [ X-Cache, { value: miss, as: equal } ]
740768

741769
# Accept-Encoding header compress, gzip would match the alternate of gzip Accept-Encoding header
742770
- client-request:
@@ -784,11 +812,6 @@ sessions:
784812
- [ X-Response-Identifier, { value: Br-Accept-Encoding, as: equal } ]
785813
- [ X-Cache, { value: hit-fresh, as: equal } ]
786814

787-
# NOTICE: This case should make Accept-Encoding header br, gzip;q=0.8 match
788-
# the alternate of br, gzip Accept-Encoding header.
789-
# However, due to the implementation of calculate_quality_of_match(),
790-
# ATS matches the alternate of gzip Accept-Encoding header.
791-
# The result is DIFFERENT from the description of proxy.config.http.normalize_ae: 3
792815
- client-request:
793816
method: "GET"
794817
version: "1.1"
@@ -808,6 +831,5 @@ sessions:
808831
status: 200
809832
headers:
810833
fields:
811-
# - [ X-Response-Identifier, { value: Br-Gzip-Accept-Encoding, as: equal } ]
812-
- [ X-Response-Identifier, { value: Gzip-Accept-Encoding, as: equal } ]
834+
- [ X-Response-Identifier, { value: Br-Gzip-Accept-Encoding, as: equal } ]
813835
- [ X-Cache, { value: hit-fresh, as: equal } ]

0 commit comments

Comments
 (0)