Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions fetch/api/redirect/redirect-count-cross-origin-worker.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Fetch in worker: redirection loop with cross-origin redirections</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#http-network-or-cache-fetch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script>
fetch_tests_from_worker(new Worker("redirect-count-cross-origin.js"));
</script>
</body>
</html>
16 changes: 16 additions & 0 deletions fetch/api/redirect/redirect-count-cross-origin.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Fetch: redirection loop, then redirection to a cross origin</title>
<meta name="help" href="https://fetch.spec.whatwg.org/#http-network-or-cache-fetch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
<body>
<script src="/common/utils.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="../resources/utils.js"></script>
<script src="redirect-count-cross-origin.js"></script>
</body>
</html>
59 changes: 59 additions & 0 deletions fetch/api/redirect/redirect-count-cross-origin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
if (this.document === undefined) {
importScripts("/resources/testharness.js");
importScripts("../resources/utils.js");
importScripts("/common/utils.js");
importScripts("/common/get-host-info.sub.js");
}

function redirectCount(desc, redirectUrl, redirectLocation, redirectStatus, maxCount1, maxCount2, requirePreflight)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redirectUrl and redirectLocation could probably be removed since they're always the same.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should not always be the same.
The principle of the test is that we will redirect macCount1 times on redirectUrl.
On the last redirect to redirectUrl, we should be redirected to redirectLocation (bad name probably)
And we again are redirected macCount2 on redirectLocation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But you always pass the same values as arguments here. There is no method call to redirectCount where they have a different value as far as I can tell.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

redirect-count.py is expected to do that (is_final_redirection check or something like that)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you're misunderstanding my feedback. My point was that they don't have to be arguments to the redirectCount() function as the redirectCount() function is never invoked with different values for them. Surely redirect-count.py is not invoking JavaScript?

{
var allow_headers = "";
var requestInit = {"redirect": "follow"};
if (requirePreflight) {
requestInit.headers = [["x-test", "test"]];
allow_headers = "&allow_headers=x-test";
}

var uuid_token = token();

var urlParameters = "?token=" + uuid_token + "&max_age=0";
urlParameters += "&redirect_status=" + redirectStatus;
urlParameters += "&max_count=" + maxCount1;
urlParameters += allow_headers;
urlParameters += "&location=" + encodeURIComponent(redirectLocation + "?token=" + uuid_token + "&max_age=0&max_count=" + (maxCount1 + maxCount2) + allow_headers);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems you're adding allow_headers and max_age twice. Also max_age is never used in the Python resource.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also set max_count twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are added to the first looped URL and the second looped URL.
Might need to check though whether this is working using a web inspector.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, yeah, that probably works.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But max_age should probably still be removed.


var maxCount = maxCount1 + maxCount2;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should move up so you don't need to do this addition twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

var url = redirectUrl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems rather redundant renaming?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

promise_test(function(test) {
return fetch(RESOURCES_DIR + "clean-stash.py?token=" + uuid_token).then(function(resp) {
assert_equals(resp.status, 200, "Clean stash response's status is 200");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's always 200, no? The only difference seems to be whether the contents are "1" or "0".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is just a safety check that the overall test env is correct.


if (maxCount > 20)
return promise_rejects(test, new TypeError(), fetch(url + urlParameters, requestInit));

return fetch(url + urlParameters, requestInit).then(function(resp) {
assert_equals(resp.status, 200, "Response's status is 200");
return resp.text();
}).then(function(body) {
assert_equals(body, maxCount.toString(), "Redirected " + maxCount + " times");
});
});
}, desc);
}

var redirUrl = "/fetch/api/resources/redirect-count.py";
var crossOriginRedirUrl = get_host_info().HTTP_ORIGIN_WITH_DIFFERENT_PORT + redirUrl;

redirectCount("Redirect 20 times, last redirection to cross-origin", redirUrl, crossOriginRedirUrl, 301, 19, 1);
redirectCount("Redirect 21 times, last redirection to cross-origin", redirUrl, crossOriginRedirUrl, 301, 20, 1);

redirectCount("Redirect 20 times, going to cross-origin after 10", redirUrl, crossOriginRedirUrl, 302, 10, 10);
redirectCount("Redirect 21 times, going to cross-origin after 10", redirUrl, crossOriginRedirUrl, 302, 10, 11);

redirectCount("Redirect 20 times, last redirection to cross-origin with preflight", redirUrl, crossOriginRedirUrl, 301, 19, 1, true);
redirectCount("Redirect 21 times, last redirection to cross-origin with preflight", redirUrl, crossOriginRedirUrl, 301, 20, 1, true);

redirectCount("Redirect 20 times, going to cross-origin after 10 with preflight", redirUrl, crossOriginRedirUrl, 303, 10, 10, true);
redirectCount("Redirect 21 times, going to cross-origin after 10 with preflight", redirUrl, crossOriginRedirUrl, 303, 10, 11, true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also test 307/308?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right


done();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain this call? I never quite understood that in the Fetch API tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it needed for worker-environment tests?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it works without.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it not for Single Page Tests?

10 changes: 4 additions & 6 deletions fetch/api/redirect/redirect-count.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,12 @@ if (this.document === undefined) {
importScripts("/common/utils.js");
}

function redirectCount(desc, redirectUrl, redirectLocation, redirectStatus, maxCount, shouldPass) {
function redirectCount(desc, redirectUrl, redirectStatus, maxCount, shouldPass) {
var uuid_token = token();

var urlParameters = "?token=" + uuid_token + "&max_age=0";
urlParameters += "&redirect_status=" + redirectStatus;
urlParameters += "&max_count=" + maxCount;
if (redirectLocation)
urlParameters += "&location=" + encodeURIComponent(redirectLocation);

var url = redirectUrl;
var requestInit = {"redirect": "follow"};
Expand All @@ -33,11 +31,11 @@ function redirectCount(desc, redirectUrl, redirectLocation, redirectStatus, maxC
}, desc);
}

var redirUrl = RESOURCES_DIR + "redirect.py";
var redirUrl = RESOURCES_DIR + "redirect-count.py";

for (var statusCode of [301, 302, 303, 307, 308]) {
redirectCount("Redirect " + statusCode + " 20 times", redirUrl, redirUrl, statusCode, 20, true);
redirectCount("Redirect " + statusCode + " 21 times", redirUrl, redirUrl, statusCode, 21, false);
redirectCount("Redirect " + statusCode + " 20 times", redirUrl, statusCode, 20, true);
redirectCount("Redirect " + statusCode + " 21 times", redirUrl, statusCode, 21, false);
}

done();
62 changes: 62 additions & 0 deletions fetch/api/resources/redirect-count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
from urllib import urlencode
from urlparse import urlparse

def main(request, response):
stashed_data = {'count': 0, 'preflight': "0"}
status = 302
headers = [("Content-Type", "text/plain"),
("Cache-Control", "no-cache"),
("Pragma", "no-cache"),
("Access-Control-Allow-Origin", "*")]
token = None

if "token" in request.GET:
token = request.GET.first("token")
data = request.server.stash.take(token)
if data:
stashed_data = data

if request.method == "OPTIONS":
if "allow_headers" in request.GET:
headers.append(("Access-Control-Allow-Headers", request.GET['allow_headers']))
stashed_data['preflight'] = "1"
#Preflight is not redirected: return 200
if not "redirect_preflight" in request.GET:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is redirect_preflight ever passed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not remember. I can check to remove it.

if token:
request.server.stash.put(request.GET.first("token"), stashed_data)
return 200, headers, ""

if "redirect_status" in request.GET:
status = int(request.GET['redirect_status'])

stashed_data['count'] += 1

is_final_redirection = False
if token:
request.server.stash.put(request.GET.first("token"), stashed_data)
if "max_count" in request.GET:
max_count = int(request.GET['max_count'])
#stop redirecting and return count
if stashed_data['count'] > max_count:
if not "location" in request.GET:
# -1 because the last is not a redirection
return 200, headers, str(stashed_data['count'] - 1)
# After max_count, let's go to the final location.
headers.append(("Location", request.GET['location']))
is_final_redirection = True

if not is_final_redirection:
# Let's redirect to the same URL except for count parameter
url = request.url.split("?")[0];
scheme = urlparse(request.url).scheme
if scheme == "" or scheme == "http" or scheme == "https":
#keep url parameters in location
url_parameters = {}
for item in request.GET.items():
if item[0] != "count":
url_parameters[item[0]] = item[1][0]
#make sure location changes during redirection loop
url += "?count=" + str(stashed_data['count']) + "&" + urlencode(url_parameters)
headers.append(("Location", url))

return status, headers, ""
13 changes: 0 additions & 13 deletions fetch/api/resources/redirect.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ def main(request, response):
if "redirect_status" in request.GET:
status = int(request.GET['redirect_status'])

stashed_data['count'] += 1

if "location" in request.GET:
url = request.GET['location']
scheme = urlparse(url).scheme
Expand All @@ -41,20 +39,9 @@ def main(request, response):
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:
headers.append(("Referrer-Policy", request.GET['redirect_referrerpolicy']))

if token:
request.server.stash.put(request.GET.first("token"), stashed_data)
if "max_count" in request.GET:
max_count = int(request.GET['max_count'])
#stop redirecting and return count
if stashed_data['count'] > max_count:
# -1 because the last is not a redirection
return str(stashed_data['count'] - 1)

return status, headers, ""