summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fetch/redirect-navigate
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/fetch/redirect-navigate')
-rw-r--r--testing/web-platform/tests/fetch/redirect-navigate/302-found-post-handler.py15
-rw-r--r--testing/web-platform/tests/fetch/redirect-navigate/302-found-post.html20
-rw-r--r--testing/web-platform/tests/fetch/redirect-navigate/preserve-fragment.html202
-rw-r--r--testing/web-platform/tests/fetch/redirect-navigate/resources/destination.html28
4 files changed, 265 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fetch/redirect-navigate/302-found-post-handler.py b/testing/web-platform/tests/fetch/redirect-navigate/302-found-post-handler.py
new file mode 100644
index 0000000000..40a224f656
--- /dev/null
+++ b/testing/web-platform/tests/fetch/redirect-navigate/302-found-post-handler.py
@@ -0,0 +1,15 @@
+from wptserve.utils import isomorphic_encode
+
+def main(request, response):
+ if request.method == u"POST":
+ response.add_required_headers = False
+ response.writer.write_status(302)
+ response.writer.write_header(b"Location", isomorphic_encode(request.url))
+ response.writer.end_headers()
+ response.writer.write(b"")
+ elif request.method == u"GET":
+ return ([(b"Content-Type", b"text/plain")],
+ b"OK")
+ else:
+ return ([(b"Content-Type", b"text/plain")],
+ b"FAIL") \ No newline at end of file
diff --git a/testing/web-platform/tests/fetch/redirect-navigate/302-found-post.html b/testing/web-platform/tests/fetch/redirect-navigate/302-found-post.html
new file mode 100644
index 0000000000..854cd329a8
--- /dev/null
+++ b/testing/web-platform/tests/fetch/redirect-navigate/302-found-post.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<!-- Step 1: send POST request to a URL which will then 302 Found redirect -->
+<title>HTTP 302 Found POST Navigation Test</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+async_test(function(t) {
+ window.addEventListener("load", function() {
+ var frame = document.getElementById("frame");
+ var link = new URL("302-found-post-handler.py", window.location.href);
+ frame.contentWindow.document.body.innerHTML = '<form action="' + link.href + '" method="POST" id="form"><input name="n"></form>';
+ frame.contentWindow.document.getElementById("form").submit();
+ frame.addEventListener("load", t.step_func_done(function() {
+ assert_equals(frame.contentWindow.document.body.textContent, "OK");
+ }));
+ });
+}, "HTTP 302 Found POST Navigation");
+</script>
+<body>
+<iframe id="frame" src="about:blank"></iframe>
diff --git a/testing/web-platform/tests/fetch/redirect-navigate/preserve-fragment.html b/testing/web-platform/tests/fetch/redirect-navigate/preserve-fragment.html
new file mode 100644
index 0000000000..682539a744
--- /dev/null
+++ b/testing/web-platform/tests/fetch/redirect-navigate/preserve-fragment.html
@@ -0,0 +1,202 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>Ensure fragment is kept across redirects</title>
+ <meta name="timeout" content="long">
+ <link rel=help href="https://www.w3.org/TR/cuap/#uri">
+ <link rel=help href="https://tools.ietf.org/html/rfc7231#section-7.1.2">
+ <link rel=help href="https://bugs.webkit.org/show_bug.cgi?id=158420">
+ <link rel=help href="https://bugs.webkit.org/show_bug.cgi?id=24175">
+ <script src="/common/get-host-info.sub.js"></script>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script>
+ let frame;
+ let message;
+
+ const HTTP_SAME_ORIGIN = "HTTP - SameOrigin";
+ const HTTPS_SAME_ORIGIN = "HTTPS - SameOrigin";
+ const HTTP_CROSS_ORIGIN = "HTTP - CrossOrigin";
+ const HTTPS_CROSS_ORIGIN = "HTTPS - CrossOrigin";
+
+ function messageReceived(f) {
+ return new Promise((resolve) => {
+ window.addEventListener("message", (e) => {
+ message = e.data;
+ resolve();
+ }, {once: true});
+ f();
+ });
+ }
+
+ function getHostname(navigation_type) {
+ switch (navigation_type) {
+ case HTTP_SAME_ORIGIN:
+ return get_host_info().HTTP_ORIGIN;
+ case HTTPS_SAME_ORIGIN:
+ return get_host_info().HTTPS_ORIGIN
+ case HTTP_CROSS_ORIGIN:
+ return get_host_info().HTTP_REMOTE_ORIGIN
+ case HTTPS_CROSS_ORIGIN:
+ return get_host_info().HTTPS_REMOTE_ORIGIN
+ }
+
+ return 'nonexistent'
+ }
+
+ // Turns |path| from a relative to this file path into a full URL, with
+ // the host being determined by one of the ORIGIN strings above.
+ function relativePathToFull(path, navigation_type) {
+ let host = getHostname(navigation_type);
+
+ const pathname = window.location.pathname;
+ const base_path = pathname.substring(0, pathname.lastIndexOf('/') + 1);
+
+ return host + base_path + path;
+ }
+
+ // Constructs a URL to redirect.py which will respond with the given
+ // redirect status |code| to the provided |to_url|. Optionally adds on a
+ // |fragment|, if provided, to use in the initial request to redirect.py
+ function buildRedirectUrl(to_url, code, fragment) {
+ to_url = encodeURIComponent(to_url);
+ let dest = `/common/redirect.py?status=${code}&location=${to_url}`;
+ if (fragment)
+ dest = dest + '#' + fragment;
+ return dest;
+ }
+
+ async function redirectTo(url, code, navigation_type, fragment) {
+ const dest = buildRedirectUrl(url, code, fragment);
+ await messageReceived( () => {
+ frame.contentWindow.location = getHostname(navigation_type) + dest;
+ });
+ }
+
+ async function doubleRedirectTo(url, code, navigation_type, fragment, intermediate_fragment) {
+ const second_redirection = buildRedirectUrl(url, code, intermediate_fragment);
+ const first_redirection = buildRedirectUrl(second_redirection, code, fragment);
+ await messageReceived( () => {
+ frame.contentWindow.location = getHostname(navigation_type) + first_redirection;
+ });
+ }
+
+ onload = () => {
+ frame = document.getElementById("frame");
+
+ // The tests in this file verify fragments are correctly propagated in
+ // a number of HTTP redirect scenarios. Each test is run for every
+ // relevant redirect status code. We also run each scenario under each
+ // combination of navigating to cross/same origin and using http/https.
+ const status_codes = [301, 302, 303, 307, 308];
+ const navigation_types = [HTTP_SAME_ORIGIN,
+ HTTPS_SAME_ORIGIN,
+ HTTP_CROSS_ORIGIN,
+ HTTPS_CROSS_ORIGIN];
+
+ for (let navigation_type of navigation_types) {
+ // Navigate to a URL with a fragment. The URL redirects to a different
+ // page. Ensure we land on the redirected page with the fragment
+ // specified in the initial navigation's URL.
+ //
+ // Redirect chain: urlA#target -> urlB
+ //
+ for (let code of status_codes) {
+ promise_test(async () => {
+ const to_url = relativePathToFull('resources/destination.html', navigation_type);
+ await redirectTo(to_url, code, navigation_type, "target");
+ assert_true(message.url.endsWith('#target'));
+ assert_equals(message.scrollY, 2000, "scrolls to fragment from initial navigation.");
+ }, `[${navigation_type}] Preserve fragment in ${code} redirect`);
+ }
+
+ // Navigate to a URL with a fragment. The URL redirects to a different
+ // URL that also contains a fragment. Ensure we land on the redirected
+ // page using the fragment specified in the redirect response and not
+ // the one in the initial navigation.
+ //
+ // Redirect chain: urlA#target -> urlB#fromRedirect
+ //
+ for (let code of status_codes) {
+ promise_test(async () => {
+ const to_url = relativePathToFull('resources/destination.html#fromRedirect', navigation_type);
+ await redirectTo(to_url, code, navigation_type, "target");
+ assert_true(message.url.endsWith('#fromRedirect'), `Unexpected fragment: ${message.url}`);
+ assert_equals(message.scrollY, 4000, "scrolls to fragment from redirect.");
+ }, `[${navigation_type}] Redirect URL fragment takes precedence in ${code} redirect`);
+ }
+
+ // Perform two redirects. The initial navigation has a fragment and
+ // will redirect to a URL that also responds with a redirect. Ensure we
+ // land on the final page with the fragment from the original
+ // navigation.
+ //
+ // Redirect chain: urlA#target -> urlB -> urlC
+ //
+ for (let code of status_codes) {
+ promise_test(async () => {
+ const to_url = relativePathToFull('resources/destination.html', navigation_type);
+ await doubleRedirectTo(to_url, code, navigation_type, "target");
+ assert_true(message.url.endsWith('#target'), `Unexpected fragment: ${message.url}`);
+ assert_equals(message.scrollY, 2000, "scrolls to fragment from initial navigation.");
+ }, `[${navigation_type}] Preserve fragment in multiple ${code} redirects`);
+ }
+
+ // Perform two redirects. The initial navigation has a fragment and
+ // will redirect to a URL that also responds with a redirect. The
+ // second redirection to the final page also has a fragment. Ensure we
+ // land on the final page with the fragment from the redirection
+ // response URL.
+ //
+ // Redirect chain: urlA#target -> urlB -> urlC#fromRedirect
+ //
+ for (let code of status_codes) {
+ promise_test(async () => {
+ const to_url = relativePathToFull('resources/destination.html#fromRedirect', navigation_type);
+ await doubleRedirectTo(to_url, code, navigation_type, "target");
+ assert_true(message.url.endsWith('#fromRedirect'), `Unexpected fragment: ${message.url}`);
+ assert_equals(message.scrollY, 4000, "scrolls to fragment from redirect.");
+ }, `[${navigation_type}] Destination URL fragment takes precedence in multiple ${code} redirects`);
+ }
+
+ // Perform two redirects. The initial navigation has a fragment and
+ // will redirect to a URL that also responds with a redirect. This
+ // time, both redirect response have a fragment. Ensure we land on the
+ // final page with the fragment from the last redirection response URL.
+ //
+ // Redirect chain: urlA#target -> urlB#intermediate -> urlC#fromRedirect
+ //
+ for (let code of status_codes) {
+ promise_test(async () => {
+ const to_url = relativePathToFull('resources/destination.html#fromRedirect', navigation_type);
+ await doubleRedirectTo(to_url, code, navigation_type, "target", "intermediate");
+ assert_true(message.url.endsWith('#fromRedirect'), `Unexpected fragment: ${message.url}`);
+ assert_equals(message.scrollY, 4000, "scrolls to fragment from redirect.");
+ }, `[${navigation_type}] Final redirect fragment takes precedence over intermediate in multiple ${code} redirects`);
+ }
+
+ // Perform two redirects. The initial navigation has a fragment and
+ // will redirect to a URL that also responds with a redirect. The first
+ // redirect response has a fragment but the second doesn't. Ensure we
+ // land on the final page with the fragment from the first redirection
+ // response URL.
+ //
+ // Redirect chain: urlA#target -> urlB#fromRedirect -> urlC
+ //
+ for (let code of status_codes) {
+ promise_test(async () => {
+ const to_url = relativePathToFull('resources/destination.html', navigation_type);
+ await doubleRedirectTo(to_url, code, navigation_type, "target", "fromRedirect");
+ assert_true(message.url.endsWith('#fromRedirect'), `Unexpected fragment: ${message.url}`);
+ assert_equals(message.scrollY, 4000, "scrolls to fragment from redirect.");
+ }, `[${navigation_type}] Preserve intermediate fragment in multiple ${code} redirects`);
+ }
+ }
+ }
+ </script>
+ </head>
+ <body>
+ <iframe id="frame" src=""></iframe>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/fetch/redirect-navigate/resources/destination.html b/testing/web-platform/tests/fetch/redirect-navigate/resources/destination.html
new file mode 100644
index 0000000000..f98c5a8cd7
--- /dev/null
+++ b/testing/web-platform/tests/fetch/redirect-navigate/resources/destination.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <style>
+ body {
+ height: 10000px;
+ margin: 0;
+ }
+ p {
+ position: absolute;
+ margin: 0;
+ }
+ </style>
+ <script>
+ window.onload = () => {
+ window.parent.postMessage({
+ url: window.location.toString(),
+ scrollY: window.scrollY
+ }, "*");
+ }
+ </script>
+ </head>
+ <body>
+ <p style="top: 2000px" id="target">Target</p>
+ <p style="top: 4000px" id="fromRedirect">Target</p>
+ </body>
+</html>