From 5a8082c2179c0e6c3d3faa6fe4a85edf33b57fd7 Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sat, 23 Mar 2019 00:54:48 -0700 Subject: [PATCH] Add a tentative WPT test for redirect handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fix added a unit test in //net. Now that the spec bug has been filed, also add a test to WPT. Mark it tentative because it does not actually reflect the specification, just actual browser behavior. See https://github.com/whatwg/fetch/issues/883 and associated bug. Bug: 942073 Change-Id: I60aeef60ec8241f483d23ec7c1fd8ce8e5949d2d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1532901 Commit-Queue: David Benjamin Auto-Submit: David Benjamin Reviewed-by: Philip Jägenstedt Cr-Commit-Position: refs/heads/master@{#643671} --- .../redirect-location-escape.tentative.any.js | 45 +++++++++++++++++++ fetch/api/resources/redirect.py | 21 ++++----- 2 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 fetch/api/redirect/redirect-location-escape.tentative.any.js diff --git a/fetch/api/redirect/redirect-location-escape.tentative.any.js b/fetch/api/redirect/redirect-location-escape.tentative.any.js new file mode 100644 index 00000000000000..2975e5fe1a9758 --- /dev/null +++ b/fetch/api/redirect/redirect-location-escape.tentative.any.js @@ -0,0 +1,45 @@ +// META: script=../resources/utils.js + +// See https://github.com/whatwg/fetch/issues/883 for the behavior covered by +// this test. As of writing, the Fetch spec has not been updated to cover these. + +// redirectLocation tests that a Location header of |locationHeader| is resolved +// to a URL which ends in |expectedUrlSuffix|. |locationHeader| is interpreted +// as a byte sequence via isomorphic encode, as described in [INFRA]. This +// allows the caller to specify byte sequences which are not valid UTF-8. +// However, this means, e.g., U+2603 must be passed in as "\xe2\x98\x83", its +// UTF-8 encoding, not "\u2603". +// +// [INFRA] https://infra.spec.whatwg.org/#isomorphic-encode +function redirectLocation( + desc, redirectUrl, locationHeader, expectedUrlSuffix) { + promise_test(function(test) { + // Note we use escape() instead of encodeURIComponent(), so that characters + // are escaped as bytes in the isomorphic encoding. + var url = redirectUrl + '?simple=1&location=' + escape(locationHeader); + + return fetch(url, {'redirect': 'follow'}).then(function(resp) { + assert_true( + resp.url.endsWith(expectedUrlSuffix), + resp.url + ' ends with ' + expectedUrlSuffix); + }); + }, desc); +} + +var redirUrl = RESOURCES_DIR + 'redirect.py'; +redirectLocation( + 'Redirect to escaped UTF-8', redirUrl, 'top.txt?%E2%98%83%e2%98%83', + 'top.txt?%E2%98%83%e2%98%83'); +redirectLocation( + 'Redirect to unescaped UTF-8', redirUrl, 'top.txt?\xe2\x98\x83', + 'top.txt?%E2%98%83'); +redirectLocation( + 'Redirect to escaped and unescaped UTF-8', redirUrl, + 'top.txt?\xe2\x98\x83%e2%98%83', 'top.txt?%E2%98%83%e2%98%83'); +redirectLocation( + 'Escaping produces double-percent', redirUrl, 'top.txt?%\xe2\x98\x83', + 'top.txt?%%E2%98%83'); +redirectLocation( + 'Redirect to invalid UTF-8', redirUrl, 'top.txt?\xff', 'top.txt?%FF'); + +done(); diff --git a/fetch/api/resources/redirect.py b/fetch/api/resources/redirect.py index 8e6f9c24b77f78..eb5c98dd52ff8b 100644 --- a/fetch/api/resources/redirect.py +++ b/fetch/api/resources/redirect.py @@ -38,16 +38,17 @@ def main(request, response): if "location" in request.GET: url = request.GET['location'] - scheme = urlparse(url).scheme - if scheme == "" or scheme == "http" or scheme == "https": - url += "&" if '?' in url else "?" - #keep url parameters in location - url_parameters = {} - for item in request.GET.items(): - url_parameters[item[0]] = item[1][0] - url += urlencode(url_parameters) - #make sure location changes during redirection loop - url += "&count=" + str(stashed_data['count']) + if "simple" not in request.GET: + scheme = urlparse(url).scheme + if scheme == "" or scheme == "http" or scheme == "https": + url += "&" if '?' in url else "?" + #keep url parameters in location + url_parameters = {} + for item in request.GET.items(): + url_parameters[item[0]] = item[1][0] + url += urlencode(url_parameters) + #make sure location changes during redirection loop + url += "&count=" + str(stashed_data['count']) headers.append(("Location", url)) if "redirect_referrerpolicy" in request.GET: