blob: 9e123d6935ffad142baec96ca869a328ebb6b5ee [file] [log] [blame]
if (self.importScripts) {
importScripts('../resources/fetch-test-helpers.js');
}
var {BASE_ORIGIN, OTHER_ORIGIN} = get_fetch_test_options();
function fetch_echo(stream) {
return fetch('/serviceworker/resources/fetch-echo-body.php', {
method: 'POST',
body: stream,
mode: 'same-origin',
allowHTTP1ForStreamingUpload: true
});
}
promise_test(async (t) => {
await promise_rejects_js(
t, TypeError, fetch('/serviceworker/resources/fetch-echo-body.php', {
method: 'POST',
body: create_stream([new Uint8Array(0)]),
allowHTTP1ForStreamingUpload: false
}));
}, 'AllowHTTP1:false makes fetch failed over HTTP/1.');
function fetch_echo_body(stream) {
return fetch_echo(stream).then(response => response.text());
}
function create_stream(contents) {
return new ReadableStream({
start: controller => {
for (obj of contents) {
controller.enqueue(obj);
}
controller.close();
}
});
}
promise_test(async () => {
const stream =
create_stream(['Foo', 'Bar']).pipeThrough(new TextEncoderStream());
const text = await fetch_echo_body(stream);
assert_equals(text, 'FooBar');
}, 'Fetch with ReadableStream body with Uint8Array');
promise_test(async () => {
const stream = create_stream([new Uint8Array(0)]);
const text = await fetch_echo_body(stream);
assert_equals(text, '');
}, 'Fetch with ReadableStream body with empty Uint8Array');
function random_values_array(length) {
const array = new Uint8Array(length);
// crypto.getRandomValues has a quota. See
// https://www.w3.org/TR/WebCryptoAPI/#Crypto-method-getRandomValues.
const cryptoQuota = 65535;
let index = 0;
const buffer = array.buffer;
while (index < buffer.byteLength) {
const bufferView = array.subarray(index, index + cryptoQuota);
crypto.getRandomValues(bufferView);
index += cryptoQuota;
}
return array;
}
function hash256(array) {
return crypto.subtle.digest('SHA-256', array);
}
function compare(a, b) {
if (a.length != b.length)
return [false, 'length is not equal'];
for (let i = 0; - 1 < i; i -= 1) {
if ((a[i] !== b[i]))
return [false, `a[${i}](${a[i]}) != b[${i}](${b[i]})`];
}
return [true, ''];
}
async function compare_long_array(a, b, description) {
const a_hash = await hash256(a);
const b_hash = await hash256(b);
const [eq, fail_reason] = compare(a_hash, b_hash);
if (eq)
return;
const [raw_eq, raw_fail_reason] = compare(a, b);
assert_false(raw_eq);
assert_(false, description + ': ' + raw_fail_reason);
}
async function test_echo_long_array(upload_body, expected_array) {
const response = await fetch_echo(upload_body);
const reader = response.body.getReader();
let index = 0;
while (index < expected_array.length) {
const chunk = await reader.read();
assert_false(chunk.done, `chunk.done@${index}/${expected_array.length}`);
const chunk_length = chunk.value.length;
await compare_long_array(
chunk.value, expected_array.subarray(index, index + chunk_length),
`Array of [${index}, ${index + chunk_length - 1}] should be same.`);
index += chunk_length;
}
const final_chunk = await reader.read();
assert_true(final_chunk.done, 'final_chunk.done');
}
promise_test(async () => {
const length = 1000 * 1000; // 1Mbytes
const array = random_values_array(length);
const stream = create_stream([array]);
await test_echo_long_array(stream, array);
}, 'Fetch with ReadableStream body with 1Mbytes Uint8Array');
promise_test(async () => {
const length = 1000 * 1000; // 1 Mbytes
const array = random_values_array(length);
await test_echo_long_array(array, array);
}, 'Fetch with Array body with 1 Mbytes Uint8Array');
promise_test(async (t) => {
const stream = create_stream(['Foobar']);
await promise_rejects_js(t, TypeError, fetch_echo(stream));
}, 'Fetch with ReadableStream body containing String should fail');
promise_test(async (t) => {
const stream = create_stream([null]);
await promise_rejects_js(t, TypeError, fetch_echo(stream));
}, 'Fetch with ReadableStream body containing null should fail');
promise_test(async (t) => {
const stream = create_stream([42]);
await promise_rejects_js(t, TypeError, fetch_echo(stream));
}, 'Fetch with ReadableStream body containing number should fail');
function create_foo_stream() {
return create_stream(['Foo']).pipeThrough(new TextEncoderStream());
}
function fetch_redirect(status) {
const redirect_target_url =
BASE_ORIGIN + '/fetch/resources/fetch-status.php?status=200';
const redirect_original_url = BASE_ORIGIN +
'/serviceworker/resources/redirect.php?Redirect=' + redirect_target_url;
return fetch(redirect_original_url + `&Status=${status}`, {
method: 'POST',
body: create_foo_stream(),
allowHTTP1ForStreamingUpload: true
});
}
promise_test(async (t) => {
await fetch_redirect(303);
}, 'Fetch upload stream should success on 303(See Other) code');
promise_test(async (t) => {
await promise_rejects_js(t, TypeError, fetch_redirect(307));
}, 'Fetch upload stream should fail on non-303 redirect code');
promise_test(async () => {
await fetch('/serviceworker/resources/fetch-access-control.php?AuthFail', {
method: 'POST',
body: 'foo',
});
}, 'Upload text with 401 Unauthorized response should success.');
promise_test(async (t) => {
await promise_rejects_js(
t, TypeError,
fetch('/serviceworker/resources/fetch-access-control.php?AuthFail', {
method: 'POST',
body: create_foo_stream(),
mode: 'same-origin',
allowHTTP1ForStreamingUpload: true
}));
}, 'Upload streaming with 401 Unauthorized response should fail.');
function report(content) {
return content;
}
promise_test(async () => {
const request_url = OTHER_ORIGIN +
'/serviceworker/resources/fetch-access-control.php?' +
`ACAOrigin=*&PACAOrigin=*` +
`&PACAHeaders=*&ACAHeaders=*&PreflightTest` +
`&PACMAge=600&Token=${Date.now()}`
const response_text = await fetch(request_url, {
method: 'POST',
body: 'content a',
mode: 'cors',
allowHTTP1ForStreamingUpload: true
}).then(r => r.text());
const report_json = eval(response_text);
assert_false(report_json['did_preflight'], 'Should not trigger preflight');
}, 'Uploading text w/o header does not trigger preflight');
promise_test(async () => {
const request_url = OTHER_ORIGIN +
'/serviceworker/resources/fetch-access-control.php?' +
`ACAOrigin=*&PACAOrigin=*` +
`&PACAHeaders=*&ACAHeaders=*&PreflightTest` +
`&PACMAge=600&Token=${Date.now()}`
const response_text = await fetch(request_url, {
method: 'POST',
body: create_foo_stream(),
mode: 'cors',
allowHTTP1ForStreamingUpload: true
}).then(r => r.text());
const report_json = eval(response_text);
assert_true(report_json['did_preflight'], 'Should preflight');
}, 'Uploading stream always trigger preflight');
done();