blob: 3680c0c471d3d5f36c4aba4cc58dcd52c38a08df [file] [log] [blame]
importScripts('/resources/testharness.js');
setup({ explicit_done: true });
function assert_range_request(request, expectedRangeHeader, name) {
assert_equals(request.headers.get('Range'), expectedRangeHeader, name);
}
async function broadcast(msg) {
for (const client of await clients.matchAll()) {
client.postMessage(msg);
}
}
addEventListener('fetch', event => {
/** @type Request */
const request = event.request;
const url = new URL(request.url);
const action = url.searchParams.get('action');
switch (action) {
case 'range-header-filter-test':
rangeHeaderFilterTest(request);
return;
case 'range-header-passthrough-test':
rangeHeaderPassthroughTest(event);
return;
case 'store-ranged-response':
storeRangedResponse(event);
return;
case 'use-stored-ranged-response':
useStoredRangeResponse(event);
return;
case 'broadcast-accept-encoding':
broadcastAcceptEncoding(event);
return;
}
});
/**
* @param {Request} request
*/
function rangeHeaderFilterTest(request) {
const rangeValue = request.headers.get('Range');
test(() => {
assert_range_request(new Request(request), rangeValue, `Untampered`);
assert_range_request(new Request(request, {}), rangeValue, `Untampered (no init props set)`);
assert_range_request(new Request(request, { __foo: 'bar' }), rangeValue, `Untampered (only invalid props set)`);
assert_range_request(new Request(request, { mode: 'cors' }), rangeValue, `More permissive mode`);
assert_range_request(request.clone(), rangeValue, `Clone`);
}, "Range headers correctly preserved");
test(() => {
assert_range_request(new Request(request, { headers: { Range: 'foo' } }), null, `Tampered - range header set`);
assert_range_request(new Request(request, { headers: {} }), null, `Tampered - empty headers set`);
assert_range_request(new Request(request, { mode: 'no-cors' }), null, `Tampered mode set`);
assert_range_request(new Request(request, { cache: 'no-cache' }), null, `Tampered cache mode set`);
}, "Range headers correctly removed");
test(() => {
let headers;
headers = new Request(request).headers;
headers.delete('does-not-exist');
assert_equals(headers.get('Range'), rangeValue, `Preserved if no header actually removed`);
headers = new Request(request).headers;
headers.append('foo', 'bar');
assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on append (due to request-no-cors guard)`);
headers = new Request(request).headers;
headers.set('foo', 'bar');
assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on set (due to request-no-cors guard)`);
headers = new Request(request).headers;
headers.append('Range', 'foo');
assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on append (due to request-no-cors guard)`);
headers = new Request(request).headers;
headers.set('Range', 'foo');
assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on set (due to request-no-cors guard)`);
headers = new Request(request).headers;
headers.append('Accept', 'whatever');
assert_equals(headers.get('Range'), null, `Stripped if header successfully appended`);
headers = new Request(request).headers;
headers.set('Accept', 'whatever');
assert_equals(headers.get('Range'), null, `Stripped if header successfully set`);
headers = new Request(request).headers;
headers.delete('Accept');
assert_equals(headers.get('Range'), null, `Stripped if header successfully deleted`);
headers = new Request(request).headers;
headers.delete('Range');
assert_equals(headers.get('Range'), null, `Stripped if range header successfully deleted`);
}, "Headers correctly filtered");
done();
}
function rangeHeaderPassthroughTest(event) {
/** @type Request */
const request = event.request;
const url = new URL(request.url);
const key = url.searchParams.get('range-received-key');
event.waitUntil(new Promise(resolve => {
promise_test(async () => {
await fetch(event.request);
const response = await fetch('stash-take.py?key=' + key);
assert_equals(await response.json(), 'range-header-received');
resolve();
}, `Include range header in network request`);
done();
}));
// Just send back any response, it isn't important for the test.
event.respondWith(new Response(''));
}
let storedRangeResponseP;
function storeRangedResponse(event) {
/** @type Request */
const request = event.request;
const id = new URL(request.url).searchParams.get('id');
storedRangeResponseP = fetch(event.request);
broadcast({ id });
// Just send back any response, it isn't important for the test.
event.respondWith(new Response(''));
}
function useStoredRangeResponse(event) {
event.respondWith(async function() {
const response = await storedRangeResponseP;
if (!response) throw Error("Expected stored range response");
return response.clone();
}());
}
function broadcastAcceptEncoding(event) {
/** @type Request */
const request = event.request;
const id = new URL(request.url).searchParams.get('id');
broadcast({
id,
acceptEncoding: request.headers.get('Accept-Encoding')
});
// Just send back any response, it isn't important for the test.
event.respondWith(new Response(''));
}