mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-08 09:30:27 +00:00
feat: HTTP add TLS fingerprint fallback (#1444)
This commit is contained in:
68 files changed
+7243
-1604
No files matched your search
+88
@@ -0,0 +1,88 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response consume empty bodies
|
||||
|
||||
function checkBodyText(test, response) {
|
||||
return response.text().then(function(bodyAsText) {
|
||||
assert_equals(bodyAsText, "", "Resolved value should be empty");
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
async function checkBodyBlob(test, response) {
|
||||
const bodyAsBlob = await response.blob();
|
||||
const body = await bodyAsBlob.text();
|
||||
|
||||
assert_equals(body, "", "Resolved value should be empty");
|
||||
assert_false(response.bodyUsed);
|
||||
}
|
||||
|
||||
function checkBodyArrayBuffer(test, response) {
|
||||
return response.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyJSON(test, response) {
|
||||
return response.json().then(
|
||||
function(bodyAsJSON) {
|
||||
assert_unreached("JSON parsing should fail");
|
||||
},
|
||||
function() {
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormData(test, response) {
|
||||
return response.formData().then(function(bodyAsFormData) {
|
||||
assert_true(bodyAsFormData instanceof FormData, "Should receive a FormData");
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkBodyFormDataError(test, response) {
|
||||
return promise_rejects_js(test, TypeError, response.formData()).then(function() {
|
||||
assert_false(response.bodyUsed);
|
||||
});
|
||||
}
|
||||
|
||||
function checkResponseWithNoBody(bodyType, checkFunction, headers = []) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(undefined, { "headers": headers });
|
||||
assert_false(response.bodyUsed);
|
||||
return checkFunction(test, response);
|
||||
}, "Consume response's body as " + bodyType);
|
||||
}
|
||||
|
||||
checkResponseWithNoBody("text", checkBodyText);
|
||||
checkResponseWithNoBody("blob", checkBodyBlob);
|
||||
checkResponseWithNoBody("arrayBuffer", checkBodyArrayBuffer);
|
||||
checkResponseWithNoBody("json (error case)", checkBodyJSON);
|
||||
checkResponseWithNoBody("formData with correct multipart type (error case)", checkBodyFormDataError, [["Content-Type", 'multipart/form-data; boundary="boundary"']]);
|
||||
checkResponseWithNoBody("formData with correct urlencoded type", checkBodyFormData, [["Content-Type", "application/x-www-form-urlencoded;charset=UTF-8"]]);
|
||||
checkResponseWithNoBody("formData without correct type (error case)", checkBodyFormDataError);
|
||||
|
||||
function checkResponseWithEmptyBody(bodyType, body, asText) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(body);
|
||||
assert_false(response.bodyUsed, "bodyUsed is false at init");
|
||||
if (asText) {
|
||||
return response.text().then(function(bodyAsString) {
|
||||
assert_equals(bodyAsString.length, 0, "Resolved value should be empty");
|
||||
assert_true(response.bodyUsed, "bodyUsed is true after being consumed");
|
||||
});
|
||||
}
|
||||
return response.arrayBuffer().then(function(bodyAsArrayBuffer) {
|
||||
assert_equals(bodyAsArrayBuffer.byteLength, 0, "Resolved value should be empty");
|
||||
assert_true(response.bodyUsed, "bodyUsed is true after being consumed");
|
||||
});
|
||||
}, "Consume empty " + bodyType + " response body as " + (asText ? "text" : "arrayBuffer"));
|
||||
}
|
||||
|
||||
checkResponseWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), false);
|
||||
checkResponseWithEmptyBody("text", "", false);
|
||||
checkResponseWithEmptyBody("blob", new Blob([], { "type" : "text/plain" }), true);
|
||||
checkResponseWithEmptyBody("text", "", true);
|
||||
checkResponseWithEmptyBody("URLSearchParams", new URLSearchParams(""), true);
|
||||
checkResponseWithEmptyBody("FormData", new FormData(), true);
|
||||
checkResponseWithEmptyBody("ArrayBuffer", new ArrayBuffer(), true);
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response consume
|
||||
// META: script=../resources/utils.js
|
||||
|
||||
promise_test(function(test) {
|
||||
var body = "";
|
||||
var response = new Response("");
|
||||
return validateStreamFromString(response.body.getReader(), "");
|
||||
}, "Read empty text response's body as readableStream");
|
||||
|
||||
promise_test(function(test) {
|
||||
var response = new Response(new Blob([], { "type" : "text/plain" }));
|
||||
return validateStreamFromString(response.body.getReader(), "");
|
||||
}, "Read empty blob response's body as readableStream");
|
||||
|
||||
var formData = new FormData();
|
||||
formData.append("name", "value");
|
||||
var textData = JSON.stringify("This is response's body");
|
||||
var blob = new Blob([textData], { "type" : "text/plain" });
|
||||
var urlSearchParamsData = "name=value";
|
||||
var urlSearchParams = new URLSearchParams(urlSearchParamsData);
|
||||
|
||||
for (const mode of [undefined, "byob"]) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(blob);
|
||||
return validateStreamFromString(response.body.getReader({ mode }), textData);
|
||||
}, `Read blob response's body as readableStream with mode=${mode}`);
|
||||
|
||||
promise_test(function(test) {
|
||||
var response = new Response(textData);
|
||||
return validateStreamFromString(response.body.getReader({ mode }), textData);
|
||||
}, `Read text response's body as readableStream with mode=${mode}`);
|
||||
|
||||
promise_test(function(test) {
|
||||
var response = new Response(urlSearchParams);
|
||||
return validateStreamFromString(response.body.getReader({ mode }), urlSearchParamsData);
|
||||
}, `Read URLSearchParams response's body as readableStream with mode=${mode}`);
|
||||
|
||||
promise_test(function(test) {
|
||||
var arrayBuffer = new ArrayBuffer(textData.length);
|
||||
var int8Array = new Int8Array(arrayBuffer);
|
||||
for (var cptr = 0; cptr < textData.length; cptr++)
|
||||
int8Array[cptr] = textData.charCodeAt(cptr);
|
||||
|
||||
return validateStreamFromString(new Response(arrayBuffer).body.getReader({ mode }), textData);
|
||||
}, `Read array buffer response's body as readableStream with mode=${mode}`);
|
||||
|
||||
promise_test(function(test) {
|
||||
var response = new Response(formData);
|
||||
return validateStreamFromPartialString(response.body.getReader({ mode }),
|
||||
"Content-Disposition: form-data; name=\"name\"\r\n\r\nvalue");
|
||||
}, `Read form data response's body as readableStream with mode=${mode}`);
|
||||
}
|
||||
|
||||
test(function() {
|
||||
assert_equals(Response.error().body, null);
|
||||
}, "Getting an error Response stream");
|
||||
|
||||
test(function() {
|
||||
assert_equals(Response.redirect("/").body, null);
|
||||
}, "Getting a redirect Response stream");
|
||||
|
||||
promise_test(async function(test) {
|
||||
var buffer = new ArrayBuffer(textData.length);
|
||||
|
||||
var body = new Response(textData).body;
|
||||
const reader = body.getReader( {mode: 'byob'} );
|
||||
|
||||
let offset = 3;
|
||||
while (offset < textData.length) {
|
||||
const {done, value} = await reader.read(new Uint8Array(buffer, offset));
|
||||
if (done) {
|
||||
break;
|
||||
}
|
||||
buffer = value.buffer;
|
||||
offset += value.byteLength;
|
||||
}
|
||||
|
||||
validateBufferFromString(buffer, `\0\0\0\"This is response's bo`, 'Buffer should be validated');
|
||||
}, `Reading with offset from Response stream`);
|
||||
@@ -0,0 +1,27 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response error
|
||||
|
||||
var invalidStatus = [0, 100, 199, 600, 1000];
|
||||
invalidStatus.forEach(function(status) {
|
||||
test(function() {
|
||||
assert_throws_js(RangeError, function() { new Response("", { "status" : status }); },
|
||||
"Expect RangeError exception when status is " + status);
|
||||
},"Throws RangeError when responseInit's status is " + status);
|
||||
});
|
||||
|
||||
var invalidStatusText = ["\n", "Ā"];
|
||||
invalidStatusText.forEach(function(statusText) {
|
||||
test(function() {
|
||||
assert_throws_js(TypeError, function() { new Response("", { "statusText" : statusText }); },
|
||||
"Expect TypeError exception " + statusText);
|
||||
},"Throws TypeError when responseInit's statusText is " + statusText);
|
||||
});
|
||||
|
||||
var nullBodyStatus = [204, 205, 304];
|
||||
nullBodyStatus.forEach(function(status) {
|
||||
test(function() {
|
||||
assert_throws_js(TypeError,
|
||||
function() { new Response("body", {"status" : status }); },
|
||||
"Expect TypeError exception ");
|
||||
},"Throws TypeError when building a response with body and a body status of " + status);
|
||||
});
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// META: global=window,worker
|
||||
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
const stream = new ReadableStream();
|
||||
stream.getReader();
|
||||
assert_throws_js(TypeError, () => new Response(stream));
|
||||
}, "Constructing a Response with a stream on which getReader() is called");
|
||||
|
||||
test(() => {
|
||||
const stream = new ReadableStream();
|
||||
stream.getReader().read();
|
||||
assert_throws_js(TypeError, () => new Response(stream));
|
||||
}, "Constructing a Response with a stream on which read() is called");
|
||||
|
||||
promise_test(async () => {
|
||||
const stream = new ReadableStream({ pull: c => c.enqueue(new Uint8Array()) }),
|
||||
reader = stream.getReader();
|
||||
await reader.read();
|
||||
reader.releaseLock();
|
||||
assert_throws_js(TypeError, () => new Response(stream));
|
||||
}, "Constructing a Response with a stream on which read() and releaseLock() are called");
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response: error static method
|
||||
|
||||
promise_test (async () => {
|
||||
const response = await fetch("../resources/data.json");
|
||||
assert_throws_js(TypeError, () => { response.headers.append("name", "value"); });
|
||||
assert_not_equals(response.headers.get("name"), "value", "response headers should be immutable");
|
||||
}, "Ensure response headers are immutable");
|
||||
@@ -0,0 +1,64 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response init: simple cases
|
||||
|
||||
var defaultValues = { "type" : "default",
|
||||
"url" : "",
|
||||
"ok" : true,
|
||||
"status" : 200,
|
||||
"statusText" : "",
|
||||
"body" : null
|
||||
};
|
||||
|
||||
var statusCodes = { "givenValues" : [200, 300, 400, 500, 599],
|
||||
"expectedValues" : [200, 300, 400, 500, 599]
|
||||
};
|
||||
var statusTexts = { "givenValues" : ["", "OK", "with space", String.fromCharCode(0x80)],
|
||||
"expectedValues" : ["", "OK", "with space", String.fromCharCode(0x80)]
|
||||
};
|
||||
var initValuesDict = { "status" : statusCodes,
|
||||
"statusText" : statusTexts
|
||||
};
|
||||
|
||||
function isOkStatus(status) {
|
||||
return 200 <= status && 299 >= status;
|
||||
}
|
||||
|
||||
var response = new Response();
|
||||
for (var attributeName in defaultValues) {
|
||||
test(function() {
|
||||
var expectedValue = defaultValues[attributeName];
|
||||
assert_equals(response[attributeName], expectedValue,
|
||||
"Expect default response." + attributeName + " is " + expectedValue);
|
||||
}, "Check default value for " + attributeName + " attribute");
|
||||
}
|
||||
|
||||
for (var attributeName in initValuesDict) {
|
||||
test(function() {
|
||||
var valuesToTest = initValuesDict[attributeName];
|
||||
for (var valueIdx in valuesToTest["givenValues"]) {
|
||||
var givenValue = valuesToTest["givenValues"][valueIdx];
|
||||
var expectedValue = valuesToTest["expectedValues"][valueIdx];
|
||||
var responseInit = {};
|
||||
responseInit[attributeName] = givenValue;
|
||||
var response = new Response("", responseInit);
|
||||
assert_equals(response[attributeName], expectedValue,
|
||||
"Expect response." + attributeName + " is " + expectedValue +
|
||||
" when initialized with " + givenValue);
|
||||
assert_equals(response.ok, isOkStatus(response.status),
|
||||
"Expect response.ok is " + isOkStatus(response.status));
|
||||
}
|
||||
}, "Check " + attributeName + " init values and associated getter");
|
||||
}
|
||||
|
||||
test(function() {
|
||||
const response1 = new Response("");
|
||||
assert_equals(response1.headers, response1.headers);
|
||||
|
||||
const response2 = new Response("", {"headers": {"X-Foo": "bar"}});
|
||||
assert_equals(response2.headers, response2.headers);
|
||||
const headers = response2.headers;
|
||||
response2.headers.set("X-Foo", "quux");
|
||||
assert_equals(headers, response2.headers);
|
||||
headers.set("X-Other-Header", "baz");
|
||||
assert_equals(headers, response2.headers);
|
||||
}, "Test that Response.headers has the [SameObject] extended attribute");
|
||||
@@ -0,0 +1,61 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response init: body and headers
|
||||
// META: script=../resources/utils.js
|
||||
|
||||
test(function() {
|
||||
var headerDict = {"name1": "value1",
|
||||
"name2": "value2",
|
||||
"name3": "value3"
|
||||
};
|
||||
var headers = new Headers(headerDict);
|
||||
var response = new Response("", { "headers" : headers })
|
||||
for (var name in headerDict) {
|
||||
assert_equals(response.headers.get(name), headerDict[name],
|
||||
"response's headers has " + name + " : " + headerDict[name]);
|
||||
}
|
||||
}, "Initialize Response with headers values");
|
||||
|
||||
function checkResponseInit(body, bodyType, expectedTextBody) {
|
||||
promise_test(function(test) {
|
||||
var response = new Response(body);
|
||||
var resHeaders = response.headers;
|
||||
var mime = resHeaders.get("Content-Type");
|
||||
assert_true(mime && mime.search(bodyType) > -1, "Content-Type header should be \"" + bodyType + "\" ");
|
||||
return response.text().then(function(bodyAsText) {
|
||||
//not equals: cannot guess formData exact value
|
||||
assert_true(bodyAsText.search(expectedTextBody) > -1, "Retrieve and verify response body");
|
||||
});
|
||||
}, "Initialize Response's body with " + bodyType);
|
||||
}
|
||||
|
||||
var blob = new Blob(["This is a blob"], {type: "application/octet-binary"});
|
||||
var formaData = new FormData();
|
||||
formaData.append("name", "value");
|
||||
var urlSearchParams = "URLSearchParams are not supported";
|
||||
//avoid test timeout if not implemented
|
||||
if (self.URLSearchParams)
|
||||
urlSearchParams = new URLSearchParams("name=value");
|
||||
var usvString = "This is a USVString"
|
||||
|
||||
checkResponseInit(blob, "application/octet-binary", "This is a blob");
|
||||
checkResponseInit(formaData, "multipart/form-data", "name=\"name\"\r\n\r\nvalue");
|
||||
checkResponseInit(urlSearchParams, "application/x-www-form-urlencoded;charset=UTF-8", "name=value");
|
||||
checkResponseInit(usvString, "text/plain;charset=UTF-8", "This is a USVString");
|
||||
|
||||
promise_test(function(test) {
|
||||
var body = "This is response body";
|
||||
var response = new Response(body);
|
||||
return validateStreamFromString(response.body.getReader(), body);
|
||||
}, "Read Response's body as readableStream");
|
||||
|
||||
promise_test(function(test) {
|
||||
var response = new Response("This is my fork", {"headers" : [["Content-Type", ""]]});
|
||||
return response.blob().then(function(blob) {
|
||||
assert_equals(blob.type, "", "Blob type should be the empty string");
|
||||
});
|
||||
}, "Testing empty Response Content-Type header");
|
||||
|
||||
test(function() {
|
||||
var response = new Response(null, {status: 204});
|
||||
assert_equals(response.body, null);
|
||||
}, "Testing null Response body");
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
test(() => {
|
||||
const response = new Response();
|
||||
assert_equals(response.headers.get("Content-Type"), null);
|
||||
}, "Default Content-Type for Response with empty body");
|
||||
|
||||
test(() => {
|
||||
const blob = new Blob([]);
|
||||
const response = new Response(blob);
|
||||
assert_equals(response.headers.get("Content-Type"), null);
|
||||
}, "Default Content-Type for Response with Blob body (no type set)");
|
||||
|
||||
test(() => {
|
||||
const blob = new Blob([], { type: "" });
|
||||
const response = new Response(blob);
|
||||
assert_equals(response.headers.get("Content-Type"), null);
|
||||
}, "Default Content-Type for Response with Blob body (empty type)");
|
||||
|
||||
test(() => {
|
||||
const blob = new Blob([], { type: "a/b; c=d" });
|
||||
const response = new Response(blob);
|
||||
assert_equals(response.headers.get("Content-Type"), "a/b; c=d");
|
||||
}, "Default Content-Type for Response with Blob body (set type)");
|
||||
|
||||
test(() => {
|
||||
const buffer = new Uint8Array();
|
||||
const response = new Response(buffer);
|
||||
assert_equals(response.headers.get("Content-Type"), null);
|
||||
}, "Default Content-Type for Response with buffer source body");
|
||||
|
||||
promise_test(async () => {
|
||||
const formData = new FormData();
|
||||
formData.append("a", "b");
|
||||
const response = new Response(formData);
|
||||
const boundary = (await response.text()).split("\r\n")[0].slice(2);
|
||||
assert_equals(
|
||||
response.headers.get("Content-Type"),
|
||||
`multipart/form-data; boundary=${boundary}`,
|
||||
);
|
||||
}, "Default Content-Type for Response with FormData body");
|
||||
|
||||
test(() => {
|
||||
const usp = new URLSearchParams();
|
||||
const response = new Response(usp);
|
||||
assert_equals(
|
||||
response.headers.get("Content-Type"),
|
||||
"application/x-www-form-urlencoded;charset=UTF-8",
|
||||
);
|
||||
}, "Default Content-Type for Response with URLSearchParams body");
|
||||
|
||||
test(() => {
|
||||
const response = new Response("");
|
||||
assert_equals(
|
||||
response.headers.get("Content-Type"),
|
||||
"text/plain;charset=UTF-8",
|
||||
);
|
||||
}, "Default Content-Type for Response with string body");
|
||||
|
||||
test(() => {
|
||||
const stream = new ReadableStream();
|
||||
const response = new Response(stream);
|
||||
assert_equals(response.headers.get("Content-Type"), null);
|
||||
}, "Default Content-Type for Response with ReadableStream body");
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
const OVERRIDE_MIME = "test/only; mime=type";
|
||||
|
||||
function responseWithOverrideMime(body) {
|
||||
return new Response(
|
||||
body,
|
||||
{ headers: { "Content-Type": OVERRIDE_MIME } },
|
||||
);
|
||||
}
|
||||
|
||||
test(() => {
|
||||
const response = responseWithOverrideMime(undefined);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with empty body");
|
||||
|
||||
test(() => {
|
||||
const blob = new Blob([]);
|
||||
const response = responseWithOverrideMime(blob);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with Blob body (no type set)");
|
||||
|
||||
test(() => {
|
||||
const blob = new Blob([], { type: "" });
|
||||
const response = responseWithOverrideMime(blob);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with Blob body (empty type)");
|
||||
|
||||
test(() => {
|
||||
const blob = new Blob([], { type: "a/b; c=d" });
|
||||
const response = responseWithOverrideMime(blob);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with Blob body (set type)");
|
||||
|
||||
test(() => {
|
||||
const buffer = new Uint8Array();
|
||||
const response = responseWithOverrideMime(buffer);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with buffer source body");
|
||||
|
||||
test(() => {
|
||||
const formData = new FormData();
|
||||
const response = responseWithOverrideMime(formData);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with FormData body");
|
||||
|
||||
test(() => {
|
||||
const usp = new URLSearchParams();
|
||||
const response = responseWithOverrideMime(usp);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with URLSearchParams body");
|
||||
|
||||
test(() => {
|
||||
const response = responseWithOverrideMime("");
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with string body");
|
||||
|
||||
test(() => {
|
||||
const stream = new ReadableStream();
|
||||
const response = responseWithOverrideMime(stream);
|
||||
assert_equals(response.headers.get("Content-Type"), OVERRIDE_MIME);
|
||||
}, "Can override Content-Type for Response with ReadableStream body");
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response: error static method
|
||||
|
||||
test(function() {
|
||||
var responseError = Response.error();
|
||||
assert_equals(responseError.type, "error", "Network error response's type is error");
|
||||
assert_equals(responseError.status, 0, "Network error response's status is 0");
|
||||
assert_equals(responseError.statusText, "", "Network error response's statusText is empty");
|
||||
assert_equals(responseError.body, null, "Network error response's body is null");
|
||||
|
||||
assert_true(responseError.headers.entries().next().done, "Headers should be empty");
|
||||
}, "Check response returned by static method error()");
|
||||
|
||||
test(function() {
|
||||
const headers = Response.error().headers;
|
||||
|
||||
// Avoid false positives if expected API is not available
|
||||
assert_true(!!headers);
|
||||
assert_equals(typeof headers.append, 'function');
|
||||
|
||||
assert_throws_js(TypeError, function () { headers.append('name', 'value'); });
|
||||
}, "the 'guard' of the Headers instance should be immutable");
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response: json static method
|
||||
|
||||
const APPLICATION_JSON = "application/json";
|
||||
const FOO_BAR = "foo/bar";
|
||||
|
||||
const INIT_TESTS = [
|
||||
[undefined, 200, "", APPLICATION_JSON, {}],
|
||||
[{ status: 400 }, 400, "", APPLICATION_JSON, {}],
|
||||
[{ statusText: "foo" }, 200, "foo", APPLICATION_JSON, {}],
|
||||
[{ headers: {} }, 200, "", APPLICATION_JSON, {}],
|
||||
[{ headers: { "content-type": FOO_BAR } }, 200, "", FOO_BAR, {}],
|
||||
[{ headers: { "x-foo": "bar" } }, 200, "", APPLICATION_JSON, { "x-foo": "bar" }],
|
||||
];
|
||||
|
||||
for (const [init, expectedStatus, expectedStatusText, expectedContentType, expectedHeaders] of INIT_TESTS) {
|
||||
promise_test(async function () {
|
||||
const response = Response.json("hello world", init);
|
||||
assert_equals(response.type, "default", "Response's type is default");
|
||||
assert_equals(response.status, expectedStatus, "Response's status is " + expectedStatus);
|
||||
assert_equals(response.statusText, expectedStatusText, "Response's statusText is " + JSON.stringify(expectedStatusText));
|
||||
assert_equals(response.headers.get("content-type"), expectedContentType, "Response's content-type is " + expectedContentType);
|
||||
for (const key in expectedHeaders) {
|
||||
assert_equals(response.headers.get(key), expectedHeaders[key], "Response's header " + key + " is " + JSON.stringify(expectedHeaders[key]));
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
assert_equals(data, "hello world", "Response's body is 'hello world'");
|
||||
}, `Check response returned by static json() with init ${JSON.stringify(init)}`);
|
||||
}
|
||||
|
||||
const nullBodyStatus = [204, 205, 304];
|
||||
for (const status of nullBodyStatus) {
|
||||
test(function () {
|
||||
assert_throws_js(
|
||||
TypeError,
|
||||
function () {
|
||||
Response.json("hello world", { status: status });
|
||||
},
|
||||
);
|
||||
}, `Throws TypeError when calling static json() with a status of ${status}`);
|
||||
}
|
||||
|
||||
promise_test(async function () {
|
||||
const response = Response.json({ foo: "bar" });
|
||||
const data = await response.json();
|
||||
assert_equals(typeof data, "object", "Response's json body is an object");
|
||||
assert_equals(data.foo, "bar", "Response's json body is { foo: 'bar' }");
|
||||
}, "Check static json() encodes JSON objects correctly");
|
||||
|
||||
test(function () {
|
||||
assert_throws_js(
|
||||
TypeError,
|
||||
function () {
|
||||
Response.json(Symbol("foo"));
|
||||
},
|
||||
);
|
||||
}, "Check static json() throws when data is not encodable");
|
||||
|
||||
test(function () {
|
||||
const a = { b: 1 };
|
||||
a.a = a;
|
||||
assert_throws_js(
|
||||
TypeError,
|
||||
function () {
|
||||
Response.json(a);
|
||||
},
|
||||
);
|
||||
}, "Check static json() throws when data is circular");
|
||||
|
||||
promise_test(async function () {
|
||||
class CustomError extends Error {
|
||||
name = "CustomError";
|
||||
}
|
||||
assert_throws_js(
|
||||
CustomError,
|
||||
function () {
|
||||
Response.json({ get foo() { throw new CustomError("bar") }});
|
||||
}
|
||||
)
|
||||
}, "Check static json() propagates JSON serializer errors");
|
||||
|
||||
const encodingChecks = [
|
||||
["𝌆", [34, 240, 157, 140, 134, 34]],
|
||||
["\uDF06\uD834", [34, 92, 117, 100, 102, 48, 54, 92, 117, 100, 56, 51, 52, 34]],
|
||||
["\uDEAD", [34, 92, 117, 100, 101, 97, 100, 34]],
|
||||
];
|
||||
|
||||
for (const [input, expected] of encodingChecks) {
|
||||
promise_test(async function () {
|
||||
const response = Response.json(input);
|
||||
const buffer = await response.arrayBuffer();
|
||||
const data = new Uint8Array(buffer);
|
||||
assert_array_equals(data, expected);
|
||||
}, `Check response returned by static json() with input ${input}`);
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response: redirect static method
|
||||
|
||||
var url = "http://test.url:1234/";
|
||||
test(function() {
|
||||
const redirectResponse = Response.redirect(url);
|
||||
assert_equals(redirectResponse.type, "default");
|
||||
assert_false(redirectResponse.redirected);
|
||||
assert_false(redirectResponse.ok);
|
||||
assert_equals(redirectResponse.status, 302, "Default redirect status is 302");
|
||||
assert_equals(redirectResponse.headers.get("Location"), url,
|
||||
"redirected response has Location header with the correct url");
|
||||
assert_equals(redirectResponse.statusText, "");
|
||||
}, "Check default redirect response");
|
||||
|
||||
[301, 302, 303, 307, 308].forEach(function(status) {
|
||||
test(function() {
|
||||
const redirectResponse = Response.redirect(url, status);
|
||||
assert_equals(redirectResponse.type, "default");
|
||||
assert_false(redirectResponse.redirected);
|
||||
assert_false(redirectResponse.ok);
|
||||
assert_equals(redirectResponse.status, status, "Redirect status is " + status);
|
||||
assert_equals(redirectResponse.headers.get("Location"), url);
|
||||
assert_equals(redirectResponse.statusText, "");
|
||||
}, "Check response returned by static method redirect(), status = " + status);
|
||||
});
|
||||
|
||||
test(function() {
|
||||
var invalidUrl = "http://:This is not an url";
|
||||
assert_throws_js(TypeError, function() { Response.redirect(invalidUrl); },
|
||||
"Expect TypeError exception");
|
||||
}, "Check error returned when giving invalid url to redirect()");
|
||||
|
||||
var invalidRedirectStatus = [200, 309, 400, 500];
|
||||
invalidRedirectStatus.forEach(function(invalidStatus) {
|
||||
test(function() {
|
||||
assert_throws_js(RangeError, function() { Response.redirect(url, invalidStatus); },
|
||||
"Expect RangeError exception");
|
||||
}, "Check error returned when giving invalid status to redirect(), status = " + invalidStatus);
|
||||
});
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
// META: global=window,worker
|
||||
// META: title=Response causes TypeError from bad chunk type
|
||||
|
||||
function runChunkTest(responseReaderMethod, testDescription) {
|
||||
promise_test(test => {
|
||||
let stream = new ReadableStream({
|
||||
start(controller) {
|
||||
controller.enqueue("not Uint8Array");
|
||||
controller.close();
|
||||
}
|
||||
});
|
||||
|
||||
return promise_rejects_js(test, TypeError,
|
||||
new Response(stream)[responseReaderMethod](),
|
||||
'TypeError should propagate'
|
||||
)
|
||||
}, testDescription)
|
||||
}
|
||||
|
||||
runChunkTest('arrayBuffer', 'ReadableStream with non-Uint8Array chunk passed to Response.arrayBuffer() causes TypeError');
|
||||
runChunkTest('blob', 'ReadableStream with non-Uint8Array chunk passed to Response.blob() causes TypeError');
|
||||
runChunkTest('bytes', 'ReadableStream with non-Uint8Array chunk passed to Response.bytes() causes TypeError');
|
||||
runChunkTest('formData', 'ReadableStream with non-Uint8Array chunk passed to Response.formData() causes TypeError');
|
||||
runChunkTest('json', 'ReadableStream with non-Uint8Array chunk passed to Response.json() causes TypeError');
|
||||
runChunkTest('text', 'ReadableStream with non-Uint8Array chunk passed to Response.text() causes TypeError');
|
||||
Reference in new issue
Block a user