diff options
Diffstat (limited to 'testing/web-platform/tests/fetch/api/resources')
31 files changed, 624 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fetch/api/resources/authentication.py b/testing/web-platform/tests/fetch/api/resources/authentication.py new file mode 100644 index 0000000000..8b6b00b087 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/authentication.py @@ -0,0 +1,14 @@ +def main(request, response): + user = request.auth.username + password = request.auth.password + + if user == b"user" and password == b"password": + return b"Authentication done" + + realm = b"test" + if b"realm" in request.GET: + realm = request.GET.first(b"realm") + + return ((401, b"Unauthorized"), + [(b"WWW-Authenticate", b'Basic realm="' + realm + b'"')], + b"Please login with credentials 'user' and 'password'") diff --git a/testing/web-platform/tests/fetch/api/resources/bad-chunk-encoding.py b/testing/web-platform/tests/fetch/api/resources/bad-chunk-encoding.py new file mode 100644 index 0000000000..94a77adead --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/bad-chunk-encoding.py @@ -0,0 +1,13 @@ +import time + +def main(request, response): + delay = float(request.GET.first(b"ms", 1000)) / 1E3 + count = int(request.GET.first(b"count", 50)) + time.sleep(delay) + response.headers.set(b"Transfer-Encoding", b"chunked") + response.write_status_headers() + time.sleep(delay) + for i in range(count): + response.writer.write_content(b"a\r\nTEST_CHUNK\r\n") + time.sleep(delay) + response.writer.write_content(b"garbage") diff --git a/testing/web-platform/tests/fetch/api/resources/basic.html b/testing/web-platform/tests/fetch/api/resources/basic.html new file mode 100644 index 0000000000..e23afd4bf6 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/basic.html @@ -0,0 +1,5 @@ +<!DOCTYPE html> +<!-- + Duplicating /common/blank.html to make service worker scoping simpler in + ../abort/serviceworker-intercepted.https.html +--> diff --git a/testing/web-platform/tests/fetch/api/resources/cache.py b/testing/web-platform/tests/fetch/api/resources/cache.py new file mode 100644 index 0000000000..4de751e30b --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/cache.py @@ -0,0 +1,18 @@ +ETAG = b'"123abc"' +CONTENT_TYPE = b"text/plain" +CONTENT = b"lorem ipsum dolor sit amet" + + +def main(request, response): + # let caching kick in if possible (conditional GET) + etag = request.headers.get(b"If-None-Match", None) + if etag == ETAG: + response.headers.set(b"X-HTTP-STATUS", 304) + response.status = (304, b"Not Modified") + return b"" + + # cache miss, so respond with the actual content + response.status = (200, b"OK") + response.headers.set(b"ETag", ETAG) + response.headers.set(b"Content-Type", CONTENT_TYPE) + return CONTENT diff --git a/testing/web-platform/tests/fetch/api/resources/clean-stash.py b/testing/web-platform/tests/fetch/api/resources/clean-stash.py new file mode 100644 index 0000000000..ee8c69ac44 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/clean-stash.py @@ -0,0 +1,6 @@ +def main(request, response): + token = request.GET.first(b"token") + if request.server.stash.take(token) is not None: + return b"1" + else: + return b"0" diff --git a/testing/web-platform/tests/fetch/api/resources/cors-top.txt b/testing/web-platform/tests/fetch/api/resources/cors-top.txt new file mode 100644 index 0000000000..83a3157d14 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/cors-top.txt @@ -0,0 +1 @@ +top
\ No newline at end of file diff --git a/testing/web-platform/tests/fetch/api/resources/cors-top.txt.headers b/testing/web-platform/tests/fetch/api/resources/cors-top.txt.headers new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/cors-top.txt.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/fetch/api/resources/data.json b/testing/web-platform/tests/fetch/api/resources/data.json new file mode 100644 index 0000000000..76519fa8cc --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/data.json @@ -0,0 +1 @@ +{"key": "value"} diff --git a/testing/web-platform/tests/fetch/api/resources/dump-authorization-header.py b/testing/web-platform/tests/fetch/api/resources/dump-authorization-header.py new file mode 100644 index 0000000000..a651aeb4e8 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/dump-authorization-header.py @@ -0,0 +1,14 @@ +def main(request, response): + headers = [(b"Content-Type", "text/html"), + (b"Cache-Control", b"no-cache")] + + if b"Origin" in request.headers: + headers.append((b"Access-Control-Allow-Origin", request.headers.get(b"Origin", b""))) + headers.append((b"Access-Control-Allow-Credentials", b"true")) + else: + headers.append((b"Access-Control-Allow-Origin", b"*")) + headers.append((b"Access-Control-Allow-Headers", b'Authorization')) + + if b"authorization" in request.headers: + return 200, headers, request.headers.get(b"Authorization") + return 200, headers, "none" diff --git a/testing/web-platform/tests/fetch/api/resources/echo-content.h2.py b/testing/web-platform/tests/fetch/api/resources/echo-content.h2.py new file mode 100644 index 0000000000..0be3ece4a5 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/echo-content.h2.py @@ -0,0 +1,7 @@ +def handle_headers(frame, request, response): + response.status = 200 + response.headers.update([('Content-Type', 'text/plain')]) + response.write_status_headers() + +def handle_data(frame, request, response): + response.writer.write_data(frame.data) diff --git a/testing/web-platform/tests/fetch/api/resources/echo-content.py b/testing/web-platform/tests/fetch/api/resources/echo-content.py new file mode 100644 index 0000000000..5e137e15d7 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/echo-content.py @@ -0,0 +1,12 @@ +from wptserve.utils import isomorphic_encode + +def main(request, response): + + headers = [(b"X-Request-Method", isomorphic_encode(request.method)), + (b"X-Request-Content-Length", request.headers.get(b"Content-Length", b"NO")), + (b"X-Request-Content-Type", request.headers.get(b"Content-Type", b"NO")), + # Avoid any kind of content sniffing on the response. + (b"Content-Type", b"text/plain")] + content = request.body + + return headers, content diff --git a/testing/web-platform/tests/fetch/api/resources/empty.txt b/testing/web-platform/tests/fetch/api/resources/empty.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/empty.txt diff --git a/testing/web-platform/tests/fetch/api/resources/infinite-slow-response.py b/testing/web-platform/tests/fetch/api/resources/infinite-slow-response.py new file mode 100644 index 0000000000..a26cd8064c --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/infinite-slow-response.py @@ -0,0 +1,35 @@ +import time + + +def url_dir(request): + return u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/' + + +def stash_write(request, key, value): + """Write to the stash, overwriting any previous value""" + request.server.stash.take(key, url_dir(request)) + request.server.stash.put(key, value, url_dir(request)) + + +def main(request, response): + stateKey = request.GET.first(b"stateKey", b"") + abortKey = request.GET.first(b"abortKey", b"") + + if stateKey: + stash_write(request, stateKey, 'open') + + response.headers.set(b"Content-type", b"text/plain") + response.write_status_headers() + + # Writing an initial 2k so browsers realise it's there. *shrug* + response.writer.write(b"." * 2048) + + while True: + if not response.writer.write(b"."): + break + if abortKey and request.server.stash.take(abortKey, url_dir(request)): + break + time.sleep(0.01) + + if stateKey: + stash_write(request, stateKey, 'closed') diff --git a/testing/web-platform/tests/fetch/api/resources/inspect-headers.py b/testing/web-platform/tests/fetch/api/resources/inspect-headers.py new file mode 100644 index 0000000000..9ed566e607 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/inspect-headers.py @@ -0,0 +1,24 @@ +def main(request, response): + headers = [] + if b"headers" in request.GET: + checked_headers = request.GET.first(b"headers").split(b"|") + for header in checked_headers: + if header in request.headers: + headers.append((b"x-request-" + header, request.headers.get(header, b""))) + + if b"cors" in request.GET: + if b"Origin" in request.headers: + headers.append((b"Access-Control-Allow-Origin", request.headers.get(b"Origin", b""))) + else: + headers.append((b"Access-Control-Allow-Origin", b"*")) + headers.append((b"Access-Control-Allow-Credentials", b"true")) + headers.append((b"Access-Control-Allow-Methods", b"GET, POST, HEAD")) + exposed_headers = [b"x-request-" + header for header in checked_headers] + headers.append((b"Access-Control-Expose-Headers", b", ".join(exposed_headers))) + if b"allow_headers" in request.GET: + headers.append((b"Access-Control-Allow-Headers", request.GET[b'allow_headers'])) + else: + headers.append((b"Access-Control-Allow-Headers", b", ".join(request.headers))) + + headers.append((b"content-type", b"text/plain")) + return headers, b"" diff --git a/testing/web-platform/tests/fetch/api/resources/keepalive-iframe.html b/testing/web-platform/tests/fetch/api/resources/keepalive-iframe.html new file mode 100644 index 0000000000..47de0da779 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/keepalive-iframe.html @@ -0,0 +1,25 @@ +<!doctype html> +<html> +<meta charset="utf-8"> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +const SEARCH_PARAMS = new URL(location.href).searchParams; +const ORIGIN1 = SEARCH_PARAMS.get('origin1') || ''; +const ORIGIN2 = SEARCH_PARAMS.get('origin2') || ''; +const WITH_HEADERS = !!SEARCH_PARAMS.has('with-headers'); +const TOKEN = token(); + +const url = + `${ORIGIN1}/fetch/api/resources/redirect.py?` + + `delay=500&` + + `allow_headers=foo&` + + `location=${ORIGIN2}/fetch/api/resources/stash-put.py?key=${TOKEN}%26value=on`; + +addEventListener('load', () => { + const headers = WITH_HEADERS ? {'foo': 'bar'} : undefined; + let p = fetch(url, {keepalive: true, headers}); + window.parent.postMessage(TOKEN, '*'); +}); +</script> +</html> diff --git a/testing/web-platform/tests/fetch/api/resources/keepalive-window.html b/testing/web-platform/tests/fetch/api/resources/keepalive-window.html new file mode 100644 index 0000000000..6ccf484644 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/keepalive-window.html @@ -0,0 +1,34 @@ +<!doctype html> +<html> +<meta charset="utf-8"> +<script src="/common/utils.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script> +const TOKEN = token(); +const { + HTTP_NOTSAMESITE_ORIGIN, + HTTP_REMOTE_ORIGIN, + HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT +} = get_host_info(); +const REDIRECT_DESTINATION = + `${HTTP_REMOTE_ORIGIN_WITH_DIFFERENT_PORT}/fetch/api/resources/stash-put.py` + + `?key=${TOKEN}&value=on`; +const URL = + `${HTTP_REMOTE_ORIGIN}/fetch/api/resources/redirect.py?` + + `delay=500&` + + `allow_headers=foo&` + + `location=${encodeURIComponent(REDIRECT_DESTINATION)}`; + +addEventListener('load', () => { + const iframe = document.createElement('iframe'); + document.body.appendChild(iframe); + iframe.contentWindow.addEventListener('unload', () => { + iframe.contentWindow.fetch(URL, {keepalive: true, headers: {foo: 'bar'}}); + }); + + window.opener.postMessage(TOKEN, '*'); + // Do NOT remove `iframe` here. We want to check the case where the nested + // frame is implicitly closed by window closure. +}); +</script> +</html> diff --git a/testing/web-platform/tests/fetch/api/resources/method.py b/testing/web-platform/tests/fetch/api/resources/method.py new file mode 100644 index 0000000000..c1a111b4cd --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/method.py @@ -0,0 +1,18 @@ +from wptserve.utils import isomorphic_encode + +def main(request, response): + headers = [] + if b"cors" in request.GET: + headers.append((b"Access-Control-Allow-Origin", b"*")) + headers.append((b"Access-Control-Allow-Credentials", b"true")) + headers.append((b"Access-Control-Allow-Methods", b"GET, POST, PUT, FOO")) + headers.append((b"Access-Control-Allow-Headers", b"x-test, x-foo")) + headers.append((b"Access-Control-Expose-Headers", b"x-request-method")) + + headers.append((b"x-request-method", isomorphic_encode(request.method))) + headers.append((b"x-request-content-type", request.headers.get(b"Content-Type", b"NO"))) + headers.append((b"x-request-content-length", request.headers.get(b"Content-Length", b"NO"))) + headers.append((b"x-request-content-encoding", request.headers.get(b"Content-Encoding", b"NO"))) + headers.append((b"x-request-content-language", request.headers.get(b"Content-Language", b"NO"))) + headers.append((b"x-request-content-location", request.headers.get(b"Content-Location", b"NO"))) + return headers, request.body diff --git a/testing/web-platform/tests/fetch/api/resources/preflight.py b/testing/web-platform/tests/fetch/api/resources/preflight.py new file mode 100644 index 0000000000..f983ef9522 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/preflight.py @@ -0,0 +1,78 @@ +def main(request, response): + headers = [(b"Content-Type", b"text/plain")] + stashed_data = {b'control_request_headers': b"", b'preflight': b"0", b'preflight_referrer': b""} + + token = None + if b"token" in request.GET: + token = request.GET.first(b"token") + + if b"origin" in request.GET: + for origin in request.GET[b'origin'].split(b", "): + headers.append((b"Access-Control-Allow-Origin", origin)) + else: + headers.append((b"Access-Control-Allow-Origin", b"*")) + + if b"clear-stash" in request.GET: + if request.server.stash.take(token) is not None: + return headers, b"1" + else: + return headers, b"0" + + if b"credentials" in request.GET: + headers.append((b"Access-Control-Allow-Credentials", b"true")) + + if request.method == u"OPTIONS": + if not b"Access-Control-Request-Method" in request.headers: + response.set_error(400, u"No Access-Control-Request-Method header") + return b"ERROR: No access-control-request-method in preflight!" + + if request.headers.get(b"Accept", b"") != b"*/*": + response.set_error(400, u"Request does not have 'Accept: */*' header") + return b"ERROR: Invalid access in preflight!" + + if b"control_request_headers" in request.GET: + stashed_data[b'control_request_headers'] = request.headers.get(b"Access-Control-Request-Headers", None) + + if b"max_age" in request.GET: + headers.append((b"Access-Control-Max-Age", request.GET[b'max_age'])) + + if b"allow_headers" in request.GET: + headers.append((b"Access-Control-Allow-Headers", request.GET[b'allow_headers'])) + + if b"allow_methods" in request.GET: + headers.append((b"Access-Control-Allow-Methods", request.GET[b'allow_methods'])) + + preflight_status = 200 + if b"preflight_status" in request.GET: + preflight_status = int(request.GET.first(b"preflight_status")) + + stashed_data[b'preflight'] = b"1" + stashed_data[b'preflight_referrer'] = request.headers.get(b"Referer", b"") + stashed_data[b'preflight_user_agent'] = request.headers.get(b"User-Agent", b"") + if token: + request.server.stash.put(token, stashed_data) + + return preflight_status, headers, b"" + + + if token: + data = request.server.stash.take(token) + if data: + stashed_data = data + + if b"checkUserAgentHeaderInPreflight" in request.GET and request.headers.get(b"User-Agent") != stashed_data[b'preflight_user_agent']: + return 400, headers, b"ERROR: No user-agent header in preflight" + + #use x-* headers for returning value to bodyless responses + headers.append((b"Access-Control-Expose-Headers", b"x-did-preflight, x-control-request-headers, x-referrer, x-preflight-referrer, x-origin")) + headers.append((b"x-did-preflight", stashed_data[b'preflight'])) + if stashed_data[b'control_request_headers'] != None: + headers.append((b"x-control-request-headers", stashed_data[b'control_request_headers'])) + headers.append((b"x-preflight-referrer", stashed_data[b'preflight_referrer'])) + headers.append((b"x-referrer", request.headers.get(b"Referer", b""))) + headers.append((b"x-origin", request.headers.get(b"Origin", b""))) + + if token: + request.server.stash.put(token, stashed_data) + + return headers, b"" diff --git a/testing/web-platform/tests/fetch/api/resources/redirect-empty-location.py b/testing/web-platform/tests/fetch/api/resources/redirect-empty-location.py new file mode 100644 index 0000000000..1a5f7feb2a --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/redirect-empty-location.py @@ -0,0 +1,3 @@ +def main(request, response): + headers = [(b"Location", b"")] + return 302, headers, b"" diff --git a/testing/web-platform/tests/fetch/api/resources/redirect.h2.py b/testing/web-platform/tests/fetch/api/resources/redirect.h2.py new file mode 100644 index 0000000000..6937014587 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/redirect.h2.py @@ -0,0 +1,14 @@ +from wptserve.utils import isomorphic_decode, isomorphic_encode + +def handle_headers(frame, request, response): + status = 302 + if b'redirect_status' in request.GET: + status = int(request.GET[b'redirect_status']) + response.status = status + + if b'location' in request.GET: + url = isomorphic_decode(request.GET[b'location']) + response.headers[b'Location'] = isomorphic_encode(url) + + response.headers.update([('Content-Type', 'text/plain')]) + response.write_status_headers() diff --git a/testing/web-platform/tests/fetch/api/resources/redirect.py b/testing/web-platform/tests/fetch/api/resources/redirect.py new file mode 100644 index 0000000000..d52ab5f3ee --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/redirect.py @@ -0,0 +1,73 @@ +import time + +from urllib.parse import urlencode, urlparse + +from wptserve.utils import isomorphic_decode, isomorphic_encode + +def main(request, response): + stashed_data = {b'count': 0, b'preflight': b"0"} + status = 302 + headers = [(b"Content-Type", b"text/plain"), + (b"Cache-Control", b"no-cache"), + (b"Pragma", b"no-cache")] + if b"Origin" in request.headers: + headers.append((b"Access-Control-Allow-Origin", request.headers.get(b"Origin", b""))) + headers.append((b"Access-Control-Allow-Credentials", b"true")) + else: + headers.append((b"Access-Control-Allow-Origin", b"*")) + + token = None + if b"token" in request.GET: + token = request.GET.first(b"token") + data = request.server.stash.take(token) + if data: + stashed_data = data + + if request.method == u"OPTIONS": + if b"allow_headers" in request.GET: + headers.append((b"Access-Control-Allow-Headers", request.GET[b'allow_headers'])) + stashed_data[b'preflight'] = b"1" + #Preflight is not redirected: return 200 + if not b"redirect_preflight" in request.GET: + if token: + request.server.stash.put(request.GET.first(b"token"), stashed_data) + return 200, headers, u"" + + if b"redirect_status" in request.GET: + status = int(request.GET[b'redirect_status']) + elif b"redirect_status" in request.POST: + status = int(request.POST[b'redirect_status']) + + stashed_data[b'count'] += 1 + + if b"location" in request.GET: + url = isomorphic_decode(request.GET[b'location']) + if b"simple" not in request.GET: + scheme = urlparse(url).scheme + if scheme == u"" or scheme == u"http" or scheme == u"https": + url += u"&" if u'?' in url else u"?" + #keep url parameters in location + url_parameters = {} + for item in request.GET.items(): + url_parameters[isomorphic_decode(item[0])] = isomorphic_decode(item[1][0]) + url += urlencode(url_parameters) + #make sure location changes during redirection loop + url += u"&count=" + str(stashed_data[b'count']) + headers.append((b"Location", isomorphic_encode(url))) + + if b"redirect_referrerpolicy" in request.GET: + headers.append((b"Referrer-Policy", request.GET[b'redirect_referrerpolicy'])) + + if b"delay" in request.GET: + time.sleep(float(request.GET.first(b"delay", 0)) / 1E3) + + if token: + request.server.stash.put(request.GET.first(b"token"), stashed_data) + if b"max_count" in request.GET: + max_count = int(request.GET[b'max_count']) + #stop redirecting and return count + if stashed_data[b'count'] > max_count: + # -1 because the last is not a redirection + return str(stashed_data[b'count'] - 1) + + return status, headers, u"" diff --git a/testing/web-platform/tests/fetch/api/resources/sandboxed-iframe.html b/testing/web-platform/tests/fetch/api/resources/sandboxed-iframe.html new file mode 100644 index 0000000000..6e5d506547 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/sandboxed-iframe.html @@ -0,0 +1,34 @@ +<!doctype html> +<html> +<script> +async function no_cors_should_be_rejected() { + let thrown = false; + try { + const resp = await fetch('top.txt'); + } catch (e) { + thrown = true; + } + if (!thrown) { + throw Error('fetching "top.txt" should be rejected.'); + } +} + +async function null_origin_should_be_accepted() { + const url = 'top.txt?pipe=header(access-control-allow-origin,null)|' + + 'header(cache-control,no-store)'; + const resp = await fetch(url); +} + +async function test() { + try { + await no_cors_should_be_rejected(); + await null_origin_should_be_accepted(); + parent.postMessage('PASS', '*'); + } catch (e) { + parent.postMessage(e.message, '*'); + } +} + +test(); +</script> +</html> diff --git a/testing/web-platform/tests/fetch/api/resources/script-with-header.py b/testing/web-platform/tests/fetch/api/resources/script-with-header.py new file mode 100644 index 0000000000..9a9c70ef5c --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/script-with-header.py @@ -0,0 +1,7 @@ +def main(request, response): + headers = [(b"Content-type", request.GET.first(b"mime"))] + if b"content" in request.GET and request.GET.first(b"content") == b"empty": + content = b'' + else: + content = b"console.log('Script loaded')" + return 200, headers, content diff --git a/testing/web-platform/tests/fetch/api/resources/stash-put.py b/testing/web-platform/tests/fetch/api/resources/stash-put.py new file mode 100644 index 0000000000..dbc7ceebb8 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/stash-put.py @@ -0,0 +1,17 @@ +from wptserve.utils import isomorphic_decode + +def main(request, response): + if request.method == u'OPTIONS': + # CORS preflight + response.headers.set(b'Access-Control-Allow-Origin', b'*') + response.headers.set(b'Access-Control-Allow-Methods', b'*') + response.headers.set(b'Access-Control-Allow-Headers', b'*') + return 'done' + + url_dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/' + key = request.GET.first(b"key") + value = request.GET.first(b"value") + # value here must be a text string. It will be json.dump()'ed in stash-take.py. + request.server.stash.put(key, isomorphic_decode(value), url_dir) + response.headers.set(b'Access-Control-Allow-Origin', b'*') + return "done" diff --git a/testing/web-platform/tests/fetch/api/resources/stash-take.py b/testing/web-platform/tests/fetch/api/resources/stash-take.py new file mode 100644 index 0000000000..e6db80dd86 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/stash-take.py @@ -0,0 +1,9 @@ +from wptserve.handlers import json_handler + + +@json_handler +def main(request, response): + dir = u'/'.join(request.url_parts.path.split(u'/')[:-1]) + u'/' + key = request.GET.first(b"key") + response.headers.set(b'Access-Control-Allow-Origin', b'*') + return request.server.stash.take(key, dir) diff --git a/testing/web-platform/tests/fetch/api/resources/status.py b/testing/web-platform/tests/fetch/api/resources/status.py new file mode 100644 index 0000000000..05a59d5a63 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/status.py @@ -0,0 +1,11 @@ +from wptserve.utils import isomorphic_encode + +def main(request, response): + code = int(request.GET.first(b"code", 200)) + text = request.GET.first(b"text", b"OMG") + content = request.GET.first(b"content", b"") + type = request.GET.first(b"type", b"") + status = (code, text) + headers = [(b"Content-Type", type), + (b"X-Request-Method", isomorphic_encode(request.method))] + return status, headers, content diff --git a/testing/web-platform/tests/fetch/api/resources/sw-intercept-abort.js b/testing/web-platform/tests/fetch/api/resources/sw-intercept-abort.js new file mode 100644 index 0000000000..19d4b189d8 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/sw-intercept-abort.js @@ -0,0 +1,19 @@ +async function messageClient(clientId, message) { + const client = await clients.get(clientId); + client.postMessage(message); +} + +addEventListener('fetch', event => { + let resolve; + const promise = new Promise(r => resolve = r); + + function onAborted() { + messageClient(event.clientId, event.request.signal.reason); + resolve(); + } + + messageClient(event.clientId, 'fetch event has arrived'); + + event.respondWith(promise.then(() => new Response('hello'))); + event.request.signal.addEventListener('abort', onAborted); +}); diff --git a/testing/web-platform/tests/fetch/api/resources/sw-intercept.js b/testing/web-platform/tests/fetch/api/resources/sw-intercept.js new file mode 100644 index 0000000000..b8166b62a5 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/sw-intercept.js @@ -0,0 +1,10 @@ +async function broadcast(msg) { + for (const client of await clients.matchAll()) { + client.postMessage(msg); + } +} + +addEventListener('fetch', event => { + event.waitUntil(broadcast(event.request.url)); + event.respondWith(fetch(event.request)); +}); diff --git a/testing/web-platform/tests/fetch/api/resources/top.txt b/testing/web-platform/tests/fetch/api/resources/top.txt new file mode 100644 index 0000000000..83a3157d14 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/top.txt @@ -0,0 +1 @@ +top
\ No newline at end of file diff --git a/testing/web-platform/tests/fetch/api/resources/trickle.py b/testing/web-platform/tests/fetch/api/resources/trickle.py new file mode 100644 index 0000000000..99833f1b38 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/trickle.py @@ -0,0 +1,15 @@ +import time + +def main(request, response): + delay = float(request.GET.first(b"ms", 500)) / 1E3 + count = int(request.GET.first(b"count", 50)) + # Read request body + request.body + time.sleep(delay) + if not b"notype" in request.GET: + response.headers.set(b"Content-type", b"text/plain") + response.write_status_headers() + time.sleep(delay) + for i in range(count): + response.writer.write_content(b"TEST_TRICKLE\n") + time.sleep(delay) diff --git a/testing/web-platform/tests/fetch/api/resources/utils.js b/testing/web-platform/tests/fetch/api/resources/utils.js new file mode 100644 index 0000000000..3b20ecc834 --- /dev/null +++ b/testing/web-platform/tests/fetch/api/resources/utils.js @@ -0,0 +1,105 @@ +var RESOURCES_DIR = "../resources/"; + +function dirname(path) { + return path.replace(/\/[^\/]*$/, '/') +} + +function checkRequest(request, ExpectedValuesDict) { + for (var attribute in ExpectedValuesDict) { + switch(attribute) { + case "headers": + for (var key in ExpectedValuesDict["headers"].keys()) { + assert_equals(request["headers"].get(key), ExpectedValuesDict["headers"].get(key), + "Check headers attribute has " + key + ":" + ExpectedValuesDict["headers"].get(key)); + } + break; + + case "body": + //for checking body's content, a dedicated asyncronous/promise test should be used + assert_true(request["headers"].has("Content-Type") , "Check request has body using Content-Type header") + break; + + case "method": + case "referrer": + case "referrerPolicy": + case "credentials": + case "cache": + case "redirect": + case "integrity": + case "url": + case "destination": + assert_equals(request[attribute], ExpectedValuesDict[attribute], "Check " + attribute + " attribute") + break; + + default: + break; + } + } +} + +function stringToArray(str) { + var array = new Uint8Array(str.length); + for (var i=0, strLen = str.length; i < strLen; i++) + array[i] = str.charCodeAt(i); + return array; +} + +function encode_utf8(str) +{ + if (self.TextEncoder) + return (new TextEncoder).encode(str); + return stringToArray(unescape(encodeURIComponent(str))); +} + +function validateBufferFromString(buffer, expectedValue, message) +{ + return assert_array_equals(new Uint8Array(buffer !== undefined ? buffer : []), stringToArray(expectedValue), message); +} + +function validateStreamFromString(reader, expectedValue, retrievedArrayBuffer) { + // Passing Uint8Array for byte streams; non-byte streams will simply ignore it + return reader.read(new Uint8Array(64)).then(function(data) { + if (!data.done) { + assert_true(data.value instanceof Uint8Array, "Fetch ReadableStream chunks should be Uint8Array"); + var newBuffer; + if (retrievedArrayBuffer) { + newBuffer = new Uint8Array(data.value.length + retrievedArrayBuffer.length); + newBuffer.set(retrievedArrayBuffer, 0); + newBuffer.set(data.value, retrievedArrayBuffer.length); + } else { + newBuffer = data.value; + } + return validateStreamFromString(reader, expectedValue, newBuffer); + } + validateBufferFromString(retrievedArrayBuffer, expectedValue, "Retrieve and verify stream"); + }); +} + +function validateStreamFromPartialString(reader, expectedValue, retrievedArrayBuffer) { + // Passing Uint8Array for byte streams; non-byte streams will simply ignore it + return reader.read(new Uint8Array(64)).then(function(data) { + if (!data.done) { + assert_true(data.value instanceof Uint8Array, "Fetch ReadableStream chunks should be Uint8Array"); + var newBuffer; + if (retrievedArrayBuffer) { + newBuffer = new Uint8Array(data.value.length + retrievedArrayBuffer.length); + newBuffer.set(retrievedArrayBuffer, 0); + newBuffer.set(data.value, retrievedArrayBuffer.length); + } else { + newBuffer = data.value; + } + return validateStreamFromPartialString(reader, expectedValue, newBuffer); + } + + var string = new TextDecoder("utf-8").decode(retrievedArrayBuffer); + return assert_true(string.search(expectedValue) != -1, "Retrieve and verify stream"); + }); +} + +// From streams tests +function delay(milliseconds) +{ + return new Promise(function(resolve) { + step_timeout(resolve, milliseconds); + }); +} |