<!DOCTYPE html>
<meta charset="utf-8">
<title>Static Router: simply skip fetch handler if pattern matches</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="resources/static-router-helpers.sub.js"></script>
<body>
<script>
const SCRIPT = 'resources/static-router-sw.js';
const ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED =
'condition-urlpattern-constructed-source-network';
const ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_IGNORE_CASE =
'condition-urlpattern-constructed-ignore-case-source-network';
const ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_RESPECT_CASE =
'condition-urlpattern-constructed-respect-case-source-network';
const ROUTER_RULE_KEY_URL_PATTERN_URLPATTERNCOMPATIBLE =
'condition-urlpattern-urlpatterncompatible-source-network';
const ROUTER_RULE_KEY_URL_PATTERN_STRING =
'condition-urlpattern-string-source-network';
const ROUTER_RULE_KEY_REQUEST = 'condition-request-source-network'
const ROUTER_RULE_KEY_URL_PATTERN_STRING_CACHE =
'condition-urlpattern-string-source-cache';
const ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_MATCH_ALL_CACHE =
'condition-urlpattern-constructed-match-all-source-cache';
const ROUTER_RULE_KEY_URLPATTERN_CACHE_WITH_NAME =
'condition-urlpattern-string-source-cache-with-name';
const ROUTER_RULE_KEY_OR = 'condition-or-source-network'
const ROUTER_RULE_KEY_NOT = 'condition-urlpattern-not-source-network';
const SCOPE = 'resources/';
const HTML_FILE = 'resources/simple.html';
const TXT_FILE = 'resources/direct.txt';
const CSV_FILE = 'resources/simple.csv';
const NOT_FILE = 'resources/not.txt';
// Warning: please prepare the corresponding `*.text.headers` files, otherwise
// iframeTest() fails to load the following files due to MIME mismatches.
const OR_TEST_FILES = [
'resources/or-test/direct1.text',
'resources/or-test/direct2.text',
'resources/or-test/does-not-exist.text',
];
iframeTest(HTML_FILE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), rnd);
}, 'Subresource load not matched with URLPattern condition');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load matched with URLPattern condition');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED, async (t, iwin, worker) => {
const rnd = randomString();
// Confirm that the given URLPatternCompatible has a wildcard pattern for the
// hostname. Also, if |urlPattern| is a consutructed URLPattern object,
// baseURL won't be set while adding router rules, thus it matches the cross
// origin request as far as other components matches. So expecting the direct
// network request and the fetch handler doesn't capture the response.
// The response is going to be a opaque.
const origin = get_host_info().HTTPS_REMOTE_ORIGIN;
const response = await iwin.fetch(
`${origin}/${TXT_FILE}?nonce=${rnd}`, {mode: 'no-cors'});
const {requests} = await get_info_from_worker(worker);
assert_equals(requests.length, 0);
assert_equals(response.type, 'opaque');
}, 'Subresource cross origin load matched with URLPattern condition via constructed object');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_IGNORE_CASE, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load matched with ignoreCase URLPattern condition');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_RESPECT_CASE, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), rnd);
}, 'Subresource load matched without ignoreCase URLPattern condition');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_URLPATTERNCOMPATIBLE, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load matched with URLPattern condition via URLPatternCompatible');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_URLPATTERNCOMPATIBLE, async (t, iwin, worker) => {
// The SW script URL is added as a baseURL when |urlPattern| is passed via
// URLPatternCompatible, and there is not |baseURL| in it. Cross
// origin request will go through the fetch handler because |baseURL| info
// complements hostname with the hostname of the SW script.
const rnd = randomString();
const origin = get_host_info().HTTPS_REMOTE_ORIGIN;
const response = await iwin.fetch(`${origin}/${TXT_FILE}?nonce=${rnd}`);
const {requests} = await get_info_from_worker(worker);
assert_equals(requests.length, 1);
assert_equals(await response.text(), rnd);
}, 'Subresource cross origin load not matched with URLPattern condition via URLPatternCompatible');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_STRING, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load matched with URLPattern condition via string');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_STRING, async (t, iwin, worker) => {
// The SW script URL is added as a baseURL when |urlPattern| is passed via
// string, and there is not |baseURL| in it. Cross origin request will go
// through the fetch handler because |baseURL| info complements hostname with
// the hostname of the SW script.
const rnd = randomString();
const origin = get_host_info().HTTPS_REMOTE_ORIGIN;
const response = await iwin.fetch(`${origin}/${TXT_FILE}?nonce=${rnd}`);
const {requests} = await get_info_from_worker(worker);
assert_equals(requests.length, 1);
assert_equals(await response.text(), rnd);
}, 'Subresource cross origin load not matched with URLPattern condition via string');
iframeTest(CSV_FILE, ROUTER_RULE_KEY_REQUEST, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd, { mode: 'no-cors' });
assert_equals(await response.text(), "matched,with,non-url,conditions\n");
}, 'Subresource load matched with RequestMode condition');
iframeTest(OR_TEST_FILES[0], ROUTER_RULE_KEY_OR, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load matched with the nested `or` condition');
iframeTest(OR_TEST_FILES[1], ROUTER_RULE_KEY_OR, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load matched with the next `or` condition');
iframeTest(OR_TEST_FILES[2], ROUTER_RULE_KEY_OR, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), rnd);
}, 'Subresource load not matched with `or` condition');
iframeTest(HTML_FILE, ROUTER_RULE_KEY_URL_PATTERN_STRING_CACHE, async (t, iwin) => {
// No need to set `resources/` because the request is dispatched from iframe.
const CACHED_FILE = 'cache.txt';
const response = await iwin.fetch(CACHED_FILE);
assert_equals(response.status, 200);
assert_equals(await response.text(), "From cache");
// This doesn't match because the cache key is wrong.
const rnd = randomString();
const response_with_param = await iwin.fetch(`${CACHED_FILE}?nonce=${rnd}`);
assert_equals(response_with_param.status, 404);
}, 'Subresource load matched with the cache source rule');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_MATCH_ALL_CACHE, async (t, iwin, worker) => {
// Send a request, which is not stored in the cache, but it exists over the network.
const rnd = randomString();
let response = await iwin.fetch(`?nonce=${rnd}`);
assert_equals(await response.text(), "Network\n");
assert_equals(response.status, 200);
// Send a request, which is not stored in the cache, and does not exist over the network.
const NON_EXISTING_FILE = 'not-found.txt';
response = await iwin.fetch(`${NON_EXISTING_FILE}?nonce=${randomString()}`);
assert_equals(response.status, 404);
// Both requests are not handled by ServiceWorker.
const {requests} = await get_info_from_worker(worker);
assert_equals(requests.length, 0);
}, 'Subresource load did not match with the cache and fallback to the network');
iframeTest(HTML_FILE, ROUTER_RULE_KEY_URLPATTERN_CACHE_WITH_NAME, async (t, iwin, worker) => {
// No need to set `resources/` because the request is dispatched from iframe.
const CACHED_FILE = 'cache.txt';
const response = await iwin.fetch(CACHED_FILE);
assert_equals(response.status, 200);
assert_equals(await response.text(), "From cache");
// This doesn't match because the cache key is wrong.
const rnd = randomString();
const response_with_param = await iwin.fetch(`${CACHED_FILE}?nonce=${rnd}`);
assert_equals(response_with_param.status, 404);
}, 'Subresource load matched with the cache source, with specifying the cache name');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_NOT, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch(`${NOT_FILE}?nonce=${rnd}`);
assert_equals(await response.text(), rnd);
}, 'Subresource load should not match with the not condition');
iframeTest(TXT_FILE, ROUTER_RULE_KEY_NOT, async (t, iwin) => {
const rnd = randomString();
const response = await iwin.fetch('?nonce=' + rnd);
assert_equals(await response.text(), "Network\n");
}, 'Subresource load should match with a file other than not');
</script>
</body>