This is an automated email from the ASF dual-hosted git repository. zwoop pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/9.0.x by this push: new f2d2e92 Allow initial // in request targets. (#7266) f2d2e92 is described below commit f2d2e92f8afd8f61eb59737f84dc78ba4e32fb27 Author: Brian Neradt <brian.ner...@gmail.com> AuthorDate: Mon Oct 12 12:25:03 2020 -0500 Allow initial // in request targets. (#7266) Allow URI's with an initial double slash, such as: //index.html Co-authored-by: bneradt <bner...@verizonmedia.com> (cherry picked from commit aa16a29e523198728dc4dfe3b00140d4e2e913bc) --- proxy/hdrs/URL.cc | 8 +--- proxy/hdrs/unit_tests/test_URL.cc | 27 ++++++++--- tests/gold_tests/url/uri.replay.yaml | 86 ++++++++++++++++++++++++++++++++++++ tests/gold_tests/url/uri.test.py | 37 ++++++++++++++++ 4 files changed, 146 insertions(+), 12 deletions(-) diff --git a/proxy/hdrs/URL.cc b/proxy/hdrs/URL.cc index c2a903b..4f7b4e8 100644 --- a/proxy/hdrs/URL.cc +++ b/proxy/hdrs/URL.cc @@ -1384,13 +1384,7 @@ url_parse_http(HdrHeap *heap, URLImpl *url, const char **start, const char *end, return err; } - cur = *start; - if (url->m_ptr_host == nullptr && ((end - cur) >= 2) && '/' == *cur && '/' == *(cur + 1)) { - // RFC 3986 section-3.3: - // If a URI does not contain an authority component, then the path cannot - // begin with two slash characters ("//"). - return PARSE_RESULT_ERROR; - } + cur = *start; bool nothing_after_host = false; if (*start == end) { nothing_after_host = true; diff --git a/proxy/hdrs/unit_tests/test_URL.cc b/proxy/hdrs/unit_tests/test_URL.cc index 975bd5e..2fef10a 100644 --- a/proxy/hdrs/unit_tests/test_URL.cc +++ b/proxy/hdrs/unit_tests/test_URL.cc @@ -64,7 +64,8 @@ TEST_CASE("ParseRulesStrictURI", "[proxy][parseuri]") const struct { const char *const uri; bool valid; - } http_strict_uri_parsing_test_case[] = {{"/home", true}, + } http_strict_uri_parsing_test_case[] = {{"//index.html", true}, + {"/home", true}, {"/path/data?key=value#id", true}, {"/ABCDEFGHIJKLMNOPQRSTUVWXYZ", true}, {"/abcdefghijklmnopqrstuvwxyz", true}, @@ -109,6 +110,22 @@ constexpr bool VERIFY_HOST_CHARACTERS = true; // clang-format off std::vector<url_parse_test_case> url_parse_test_cases = { { + "/index.html", + "/index.html", + VERIFY_HOST_CHARACTERS, + "/index.html", + IS_VALID, + IS_VALID + }, + { + "//index.html", + "//index.html", + VERIFY_HOST_CHARACTERS, + "//index.html", + IS_VALID, + IS_VALID + }, + { // The following scheme-only URI is technically valid per the spec, but we // have historically returned this as invalid and I'm not comfortable // changing it in case something depends upon this behavior. Besides, a @@ -131,13 +148,13 @@ std::vector<url_parse_test_case> url_parse_test_cases = { }, { // RFC 3986 section-3: When authority is not present, the path cannot begin - // with two slash characters ("//"). The parse_regex, though, is more - // forgiving. + // with two slash characters ("//"). We have historically allowed this, + // however, and will continue to do so. + "https:////", "https:////", - "", VERIFY_HOST_CHARACTERS, "https:////", - !IS_VALID, + IS_VALID, IS_VALID }, { diff --git a/tests/gold_tests/url/uri.replay.yaml b/tests/gold_tests/url/uri.replay.yaml new file mode 100644 index 0000000..4935ff7 --- /dev/null +++ b/tests/gold_tests/url/uri.replay.yaml @@ -0,0 +1,86 @@ +# 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. + +# +# This replay file assumes that caching is enabled and +# proxy.config.http.cache.ignore_client_cc_max_age is set to 0 so that we can +# test max-age in the client requests. +# + +meta: + version: "1.0" + + blocks: + - 200_ok_response: &200_ok_response + server-response: + status: 200 + reason: OK + headers: + fields: + - [ Content-Length, 16 ] + - [ Cache-Control, max-age=300 ] + +sessions: +- transactions: + + # A simply path + - all: { headers: { fields: [[ uuid, 1 ]]}} + client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: /index.html + headers: + fields: + - [ Host, example.com ] + + <<: *200_ok_response + + proxy-response: + status: 200 + + # An initial // without an authority is not valid per RFC 3986 section-3.3, + # but we have historically accepted it and will continue to do so. + - all: { headers: { fields: [[ uuid, 2 ]]}} + client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: //index.html + headers: + fields: + - [ Host, example.com ] + + <<: *200_ok_response + + proxy-response: + status: 200 + + # A '^' is an invalid path. + - all: { headers: { fields: [[ uuid, 3 ]]}} + client-request: + method: "GET" + version: "1.1" + scheme: "http" + url: ^ + headers: + fields: + - [ Host, example.com ] + + <<: *200_ok_response + + proxy-response: + status: 400 diff --git a/tests/gold_tests/url/uri.test.py b/tests/gold_tests/url/uri.test.py new file mode 100644 index 0000000..8589d07 --- /dev/null +++ b/tests/gold_tests/url/uri.test.py @@ -0,0 +1,37 @@ +''' +Verify correct URI parsing behavior. +''' +# 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 = ''' +Verify correct URI parsing behavior. +''' + +ts = Test.MakeATSProcess("ts") +replay_file = "uri.replay.yaml" +server = Test.MakeVerifierServerProcess("server", replay_file) +ts.Disk.records_config.update({ + 'proxy.config.diags.debug.enabled': 1, + 'proxy.config.diags.debug.tags': 'http', +}) +ts.Disk.remap_config.AddLine( + 'map / http://127.0.0.1:{0}'.format(server.Variables.http_port) +) +tr = Test.AddTestRun("Verify correct URI parsing behavior.") +tr.Processes.Default.StartBefore(server) +tr.Processes.Default.StartBefore(ts) +tr.AddVerifierClientProcess("client", replay_file, http_ports=[ts.Variables.port])