This is an automated email from the ASF dual-hosted git repository. bcall pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push: new 47ec777 Don't send image/webp responses from cache to broswers that don't support it (#7104) 47ec777 is described below commit 47ec777f0c41ba71a208184dbebda691037218fb Author: Bryan Call <bc...@apache.org> AuthorDate: Fri Aug 14 11:58:57 2020 -0700 Don't send image/webp responses from cache to broswers that don't support it (#7104) --- proxy/http/HttpTransactCache.cc | 43 ++++++------ tests/gold_tests/headers/accept_webp.test.py | 79 ++++++++++++++++++++++ tests/gold_tests/headers/gold/accept_webp.gold | 16 +++++ .../gold_tests/headers/gold/accept_webp_cache.gold | 16 +++++ .../gold_tests/headers/gold/accept_webp_jpeg.gold | 16 +++++ 5 files changed, 150 insertions(+), 20 deletions(-) diff --git a/proxy/http/HttpTransactCache.cc b/proxy/http/HttpTransactCache.cc index 8aa3169..622f801 100644 --- a/proxy/http/HttpTransactCache.cc +++ b/proxy/http/HttpTransactCache.cc @@ -486,13 +486,6 @@ HttpTransactCache::calculate_quality_of_match(const OverridableHttpConfigParams @return quality (-1: no match, 0..1: poor..good). */ -static inline bool -do_content_types_match(char *type1, char *subtype1, char *type2, char *subtype2) -{ - return ((is_asterisk(type1) || is_empty(type1) || (strcasecmp(type1, type2) == 0)) && - (is_asterisk(subtype1) || is_empty(subtype1) || (strcasecmp(subtype1, subtype2) == 0))); -} - float HttpTransactCache::calculate_quality_of_accept_match(MIMEField *accept_field, MIMEField *content_field) { @@ -526,6 +519,9 @@ HttpTransactCache::calculate_quality_of_accept_match(MIMEField *accept_field, MI // Parse the type and subtype of the Content-Type field. HttpCompat::parse_mime_type(c_param->str, c_type, c_subtype, sizeof(c_type), sizeof(c_subtype)); + // Special case for webp because Safari is has Accept: */*, but doesn't support webp + bool content_type_webp = ((strcasecmp("webp", c_subtype) == 0) && (strcasecmp("image", c_type) == 0)); + // Now loop over Accept field values. // TODO: Should we check the return value (count) from this? accept_field->value_get_comma_list(&a_values_list); @@ -549,19 +545,25 @@ HttpTransactCache::calculate_quality_of_accept_match(MIMEField *accept_field, MI char a_type[32], a_subtype[32]; HttpCompat::parse_mime_type(a_param->str, a_type, a_subtype, sizeof(a_type), sizeof(a_subtype)); - // printf("matching Content-type; '%s/%s' with Accept value '%s/%s'\n", - // c_type,c_subtype,a_type,a_subtype); - - // Is there a wildcard in the type or subtype? - if (is_asterisk(a_type)) { - wildcard_type_present = true; - wildcard_type_q = HttpCompat::find_Q_param_in_strlist(&a_param_list); - } else if (is_asterisk(a_subtype) && (strcasecmp(a_type, c_type) == 0)) { - wildcard_subtype_present = true; - wildcard_subtype_q = HttpCompat::find_Q_param_in_strlist(&a_param_list); - } else { - // No wildcard. Do explicit matching of accept and content values. - if (do_content_types_match(a_type, a_subtype, c_type, c_subtype)) { + Debug("http_match", "matching Content-type; '%s/%s' with Accept value '%s/%s'\n", c_type, c_subtype, a_type, a_subtype); + + bool wildcard_found = true; + // Only do wildcard checks if the content type is not image/webp + if (content_type_webp == false) { + // Is there a wildcard in the type or subtype? + if (is_asterisk(a_type)) { + wildcard_type_present = true; + wildcard_type_q = HttpCompat::find_Q_param_in_strlist(&a_param_list); + } else if (is_asterisk(a_subtype) && (strcasecmp(a_type, c_type) == 0)) { + wildcard_subtype_present = true; + wildcard_subtype_q = HttpCompat::find_Q_param_in_strlist(&a_param_list); + } else { + wildcard_found = false; + } + } + if (content_type_webp == true || wildcard_found == false) { + // No wildcard or the content type is image/webp. Do explicit matching of accept and content values. + if ((strcasecmp(a_type, c_type) == 0) && (strcasecmp(a_subtype, c_subtype) == 0)) { float tq; tq = HttpCompat::find_Q_param_in_strlist(&a_param_list); q = (tq > q ? tq : q); @@ -582,6 +584,7 @@ HttpTransactCache::calculate_quality_of_accept_match(MIMEField *accept_field, MI if ((q == -1.0) && (wildcard_type_present == true)) { q = wildcard_type_q; } + return (q); } diff --git a/tests/gold_tests/headers/accept_webp.test.py b/tests/gold_tests/headers/accept_webp.test.py new file mode 100644 index 0000000..26998fd --- /dev/null +++ b/tests/gold_tests/headers/accept_webp.test.py @@ -0,0 +1,79 @@ +''' +Test how we handle image/webp +''' +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +Test.Summary = ''' +Checking that we don't serve image/webp to clients that do not support it +''' + +Test.ContinueOnFail = True + +# Define default ATS +ts = Test.MakeATSProcess("ts") +server = Test.MakeOriginServer("server") + +testName = "accept_webp" +request_header = { + "headers": "GET / HTTP/1.1\r\nHost: www.example.com\r\nAccept: image/webp,image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5\r\n\r\n", + "timestamp": "1469733493.993", + "body": ""} +response_header = { + "headers": "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: image/webp\r\nCache-Control: max-age=300\r\n", + "timestamp": "1469733493.993", + "body": "xxx"} +server.addResponse("sessionlog.json", request_header, response_header) + +# ATS Configuration +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http_match', + 'proxy.config.http.cache.ignore_accept_mismatch': 0, + 'proxy.config.http.insert_response_via_str': 3, + 'proxy.config.http.cache.http': 1, + 'proxy.config.http.wait_for_cache': 1, +}) + +ts.Disk.remap_config.AddLine( + 'map http://www.example.com http://127.0.0.1:{0}'.format(server.Variables.Port) +) + +# Test 1 - Request with image/webp support from the origin +tr = Test.AddTestRun() +tr.Processes.Default.StartBefore(server, ready=When.PortOpen(server.Variables.Port)) +tr.Processes.Default.StartBefore(Test.Processes.ts) +tr.Processes.Default.Command = 'curl -s -D - -v --ipv4 --http1.1 -H "Accept: image/webp,image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5" -H "Host: www.example.com" http://localhost:{0}/'.format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Streams.stderr = "gold/accept_webp.gold" +tr.StillRunningAfter = ts + +# Test 2 - Request with image/webp support from cache +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl -s -D - -v --ipv4 --http1.1 -H "Accept: image/webp,image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5" -H "Host: www.example.com" http://localhost:{0}/'.format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Streams.stderr = "gold/accept_webp_cache.gold" +tr.StillRunningAfter = ts + +# Test 3 - Request without image/webp support going to the origin - NOTE: the origin can't change the content-type :( +tr = Test.AddTestRun() +tr.Processes.Default.Command = 'curl -s -D - -v --ipv4 --http1.1 -H "Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5" -H "Host: www.example.com" http://localhost:{0}/'.format( + ts.Variables.port) +tr.Processes.Default.ReturnCode = 0 +tr.Processes.Default.Streams.stderr = "gold/accept_webp_jpeg.gold" +tr.StillRunningAfter = ts diff --git a/tests/gold_tests/headers/gold/accept_webp.gold b/tests/gold_tests/headers/gold/accept_webp.gold new file mode 100644 index 0000000..9b6dcb4 --- /dev/null +++ b/tests/gold_tests/headers/gold/accept_webp.gold @@ -0,0 +1,16 @@ +`` +> GET /`` +> Host: www.example.com`` +> User-Agent: curl/`` +> Accept: image/webp,image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5 +`` +< HTTP/1.1 200 OK +< Content-Type: image/webp +< Cache-Control: max-age=300 +< Content-Length: 3 +< Date: `` +< Age: `` +< Connection: keep-alive +< Via: http/1.1 `` (ApacheTrafficServer/`` [uScMsSfWpSeN:t cCMp sS]) +< Server: ATS/`` +`` diff --git a/tests/gold_tests/headers/gold/accept_webp_cache.gold b/tests/gold_tests/headers/gold/accept_webp_cache.gold new file mode 100644 index 0000000..5e2cf84 --- /dev/null +++ b/tests/gold_tests/headers/gold/accept_webp_cache.gold @@ -0,0 +1,16 @@ +`` +> GET /`` +> Host: www.example.com`` +> User-Agent: curl/`` +> Accept: image/webp,image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5 +`` +< HTTP/1.1 200 OK +< Content-Type: image/webp +< Cache-Control: max-age=300 +< Content-Length: 3 +< Date: `` +< Age: `` +< Connection: keep-alive +< Via: http/1.1 `` (ApacheTrafficServer/`` [uScHs f p eN:t cCHp s ]) +< Server: ATS/`` +`` diff --git a/tests/gold_tests/headers/gold/accept_webp_jpeg.gold b/tests/gold_tests/headers/gold/accept_webp_jpeg.gold new file mode 100644 index 0000000..1e76ccc --- /dev/null +++ b/tests/gold_tests/headers/gold/accept_webp_jpeg.gold @@ -0,0 +1,16 @@ +`` +> GET /`` +> Host: www.example.com`` +> User-Agent: curl/`` +> Accept: image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5 +`` +< HTTP/1.1 200 OK +< Content-Type: image/webp +< Cache-Control: max-age=300 +< Content-Length: 3 +< Date: `` +< Age: `` +< Connection: keep-alive +< Via: http/1.1 `` (ApacheTrafficServer/`` [uScMsSfWpSeN:t cCMp sS]) +< Server: ATS/`` +``