mirror of
https://github.com/denoland/deno.git
synced 2025-01-03 12:58:54 -05:00
fix(fetch): proxy body for requests created from other requests (#11093)
Additionally, if the existing `Request`'s body is disturbed, the Request creation should fail. This change also updates the step numbers in the Request constructor to match whatwg/fetch#1249.
This commit is contained in:
parent
2c4ce26f0b
commit
edab21ebab
5 changed files with 45 additions and 19 deletions
|
@ -19,7 +19,7 @@
|
||||||
const { parseFormData, formDataFromEntries, formDataToBlob } =
|
const { parseFormData, formDataFromEntries, formDataToBlob } =
|
||||||
globalThis.__bootstrap.formData;
|
globalThis.__bootstrap.formData;
|
||||||
const mimesniff = globalThis.__bootstrap.mimesniff;
|
const mimesniff = globalThis.__bootstrap.mimesniff;
|
||||||
const { isReadableStreamDisturbed, errorReadableStream } =
|
const { isReadableStreamDisturbed, errorReadableStream, createProxy } =
|
||||||
globalThis.__bootstrap.streams;
|
globalThis.__bootstrap.streams;
|
||||||
|
|
||||||
class InnerBody {
|
class InnerBody {
|
||||||
|
@ -133,6 +133,23 @@
|
||||||
second.length = this.length;
|
second.length = this.length;
|
||||||
return second;
|
return second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {InnerBody}
|
||||||
|
*/
|
||||||
|
createProxy() {
|
||||||
|
let proxyStreamOrStatic;
|
||||||
|
if (this.streamOrStatic instanceof ReadableStream) {
|
||||||
|
proxyStreamOrStatic = createProxy(this.streamOrStatic);
|
||||||
|
} else {
|
||||||
|
proxyStreamOrStatic = { ...this.streamOrStatic };
|
||||||
|
this.streamOrStatic.consumed = true;
|
||||||
|
}
|
||||||
|
const proxy = new InnerBody(proxyStreamOrStatic);
|
||||||
|
proxy.source = this.source;
|
||||||
|
proxy.length = this.length;
|
||||||
|
return proxy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -257,14 +257,16 @@
|
||||||
|
|
||||||
// 28.
|
// 28.
|
||||||
this[_signal] = abortSignal.newSignal();
|
this[_signal] = abortSignal.newSignal();
|
||||||
|
|
||||||
|
// 29.
|
||||||
if (signal !== null) {
|
if (signal !== null) {
|
||||||
abortSignal.follow(this[_signal], signal);
|
abortSignal.follow(this[_signal], signal);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 29.
|
// 30.
|
||||||
this[_headers] = headersFromHeaderList(request.headerList, "request");
|
this[_headers] = headersFromHeaderList(request.headerList, "request");
|
||||||
|
|
||||||
// 31.
|
// 32.
|
||||||
if (Object.keys(init).length > 0) {
|
if (Object.keys(init).length > 0) {
|
||||||
let headers = headerListFromHeaders(this[_headers]).slice(
|
let headers = headerListFromHeaders(this[_headers]).slice(
|
||||||
0,
|
0,
|
||||||
|
@ -280,13 +282,13 @@
|
||||||
fillHeaders(this[_headers], headers);
|
fillHeaders(this[_headers], headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 32.
|
// 33.
|
||||||
let inputBody = null;
|
let inputBody = null;
|
||||||
if (input instanceof Request) {
|
if (input instanceof Request) {
|
||||||
inputBody = input[_body];
|
inputBody = input[_body];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 33.
|
// 34.
|
||||||
if (
|
if (
|
||||||
(request.method === "GET" || request.method === "HEAD") &&
|
(request.method === "GET" || request.method === "HEAD") &&
|
||||||
((init.body !== undefined && init.body !== null) ||
|
((init.body !== undefined && init.body !== null) ||
|
||||||
|
@ -295,10 +297,10 @@
|
||||||
throw new TypeError("Request with GET/HEAD method cannot have body.");
|
throw new TypeError("Request with GET/HEAD method cannot have body.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 34.
|
// 35.
|
||||||
let initBody = null;
|
let initBody = null;
|
||||||
|
|
||||||
// 35.
|
// 36.
|
||||||
if (init.body !== undefined && init.body !== null) {
|
if (init.body !== undefined && init.body !== null) {
|
||||||
const res = extractBody(init.body);
|
const res = extractBody(init.body);
|
||||||
initBody = res.body;
|
initBody = res.body;
|
||||||
|
@ -307,20 +309,22 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 36.
|
// 37.
|
||||||
const inputOrInitBody = initBody ?? inputBody;
|
const inputOrInitBody = initBody ?? inputBody;
|
||||||
|
|
||||||
// 38.
|
|
||||||
const finalBody = inputOrInitBody;
|
|
||||||
|
|
||||||
// 39.
|
// 39.
|
||||||
// TODO(lucacasonato): implement this step. Is it needed?
|
let finalBody = inputOrInitBody;
|
||||||
|
|
||||||
// 40.
|
// 40.
|
||||||
request.body = finalBody;
|
if (initBody === null && inputBody !== null) {
|
||||||
|
if (input[_body] && input[_body].unusable()) {
|
||||||
|
throw new TypeError("Input request's body is unusable.");
|
||||||
|
}
|
||||||
|
finalBody = inputBody.createProxy();
|
||||||
|
}
|
||||||
|
|
||||||
// 41.
|
// 41.
|
||||||
// TODO(lucacasonato): Extranious? https://github.com/whatwg/fetch/issues/1249
|
request.body = finalBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
get method() {
|
get method() {
|
||||||
|
|
|
@ -4246,6 +4246,13 @@
|
||||||
|
|
||||||
webidl.configurePrototype(WritableStreamDefaultController);
|
webidl.configurePrototype(WritableStreamDefaultController);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ReadableStream} stream
|
||||||
|
*/
|
||||||
|
function createProxy(stream) {
|
||||||
|
return stream.pipeThrough(new TransformStream());
|
||||||
|
}
|
||||||
|
|
||||||
webidl.converters.ReadableStream = webidl
|
webidl.converters.ReadableStream = webidl
|
||||||
.createInterfaceConverter("ReadableStream", ReadableStream);
|
.createInterfaceConverter("ReadableStream", ReadableStream);
|
||||||
webidl.converters.WritableStream = webidl
|
webidl.converters.WritableStream = webidl
|
||||||
|
@ -4403,6 +4410,7 @@
|
||||||
// Non-Public
|
// Non-Public
|
||||||
isReadableStreamDisturbed,
|
isReadableStreamDisturbed,
|
||||||
errorReadableStream,
|
errorReadableStream,
|
||||||
|
createProxy,
|
||||||
// Exposed in global runtime scope
|
// Exposed in global runtime scope
|
||||||
ByteLengthQueuingStrategy,
|
ByteLengthQueuingStrategy,
|
||||||
CountQueuingStrategy,
|
CountQueuingStrategy,
|
||||||
|
|
1
extensions/web/internal.d.ts
vendored
1
extensions/web/internal.d.ts
vendored
|
@ -81,6 +81,7 @@ declare namespace globalThis {
|
||||||
declare var streams: {
|
declare var streams: {
|
||||||
ReadableStream: typeof ReadableStream;
|
ReadableStream: typeof ReadableStream;
|
||||||
isReadableStreamDisturbed(stream: ReadableStream): boolean;
|
isReadableStreamDisturbed(stream: ReadableStream): boolean;
|
||||||
|
createProxy<T>(stream: ReadableStream<T>): ReadableStream<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
declare namespace messagePort {
|
declare namespace messagePort {
|
||||||
|
|
|
@ -700,11 +700,7 @@
|
||||||
"api": {
|
"api": {
|
||||||
"request": {
|
"request": {
|
||||||
"request-init-002.any.html": true,
|
"request-init-002.any.html": true,
|
||||||
"request-init-stream.any.html": [
|
"request-init-stream.any.html": true,
|
||||||
"Constructing a Request with a Request on which body.getReader() is called",
|
|
||||||
"Constructing a Request with a Request on which body.getReader().read() is called",
|
|
||||||
"Constructing a Request with a Request on which read() and releaseLock() are called"
|
|
||||||
],
|
|
||||||
"request-consume-empty.any.html": [
|
"request-consume-empty.any.html": [
|
||||||
"Consume empty FormData request body as text"
|
"Consume empty FormData request body as text"
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue