mirror of
https://github.com/denoland/deno.git
synced 2025-03-10 06:07:03 -04:00
fix(ext/fetch) Fix request clone error in flash server (#16174)
This commit is contained in:
parent
e989882162
commit
d731f1bf35
4 changed files with 91 additions and 7 deletions
|
@ -2328,6 +2328,45 @@ Deno.test(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// https://github.com/denoland/deno/issues/15858
|
||||||
|
Deno.test(
|
||||||
|
{ permissions: { net: true } },
|
||||||
|
async function httpServerCanCloneRequest() {
|
||||||
|
const ac = new AbortController();
|
||||||
|
const listeningPromise = deferred();
|
||||||
|
|
||||||
|
const server = Deno.serve({
|
||||||
|
handler: async (req) => {
|
||||||
|
const cloned = req.clone();
|
||||||
|
assertEquals(req.headers, cloned.headers);
|
||||||
|
|
||||||
|
// both requests can read body
|
||||||
|
await req.text();
|
||||||
|
await cloned.json();
|
||||||
|
|
||||||
|
return new Response("ok");
|
||||||
|
},
|
||||||
|
signal: ac.signal,
|
||||||
|
onListen: onListen(listeningPromise),
|
||||||
|
onError: createOnErrorCb(ac),
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await listeningPromise;
|
||||||
|
const resp = await fetch("http://localhost:9000/", {
|
||||||
|
headers: { connection: "close" },
|
||||||
|
method: "POST",
|
||||||
|
body: '{"sus":true}',
|
||||||
|
});
|
||||||
|
const text = await resp.text();
|
||||||
|
assertEquals(text, "ok");
|
||||||
|
} finally {
|
||||||
|
ac.abort();
|
||||||
|
await server;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
// Checks large streaming response
|
// Checks large streaming response
|
||||||
// https://github.com/denoland/deno/issues/16567
|
// https://github.com/denoland/deno/issues/16567
|
||||||
Deno.test(
|
Deno.test(
|
||||||
|
|
|
@ -155,9 +155,11 @@
|
||||||
/**
|
/**
|
||||||
* https://fetch.spec.whatwg.org/#concept-request-clone
|
* https://fetch.spec.whatwg.org/#concept-request-clone
|
||||||
* @param {InnerRequest} request
|
* @param {InnerRequest} request
|
||||||
|
* @param {boolean} skipBody
|
||||||
|
* @param {boolean} flash
|
||||||
* @returns {InnerRequest}
|
* @returns {InnerRequest}
|
||||||
*/
|
*/
|
||||||
function cloneInnerRequest(request, skipBody = false) {
|
function cloneInnerRequest(request, skipBody = false, flash = false) {
|
||||||
const headerList = ArrayPrototypeMap(
|
const headerList = ArrayPrototypeMap(
|
||||||
request.headerList,
|
request.headerList,
|
||||||
(x) => [x[0], x[1]],
|
(x) => [x[0], x[1]],
|
||||||
|
@ -168,6 +170,19 @@
|
||||||
body = request.body.clone();
|
body = request.body.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flash) {
|
||||||
|
return {
|
||||||
|
body,
|
||||||
|
methodCb: request.methodCb,
|
||||||
|
urlCb: request.urlCb,
|
||||||
|
headerList: request.headerList,
|
||||||
|
streamRid: request.streamRid,
|
||||||
|
serverId: request.serverId,
|
||||||
|
redirectMode: "follow",
|
||||||
|
redirectCount: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
method: request.method,
|
method: request.method,
|
||||||
headerList,
|
headerList,
|
||||||
|
@ -487,16 +502,30 @@
|
||||||
}
|
}
|
||||||
let newReq;
|
let newReq;
|
||||||
if (this[_flash]) {
|
if (this[_flash]) {
|
||||||
newReq = cloneInnerRequest(this[_flash]);
|
newReq = cloneInnerRequest(this[_flash], false, true);
|
||||||
} else {
|
} else {
|
||||||
newReq = cloneInnerRequest(this[_request]);
|
newReq = cloneInnerRequest(this[_request]);
|
||||||
}
|
}
|
||||||
const newSignal = abortSignal.newSignal();
|
const newSignal = abortSignal.newSignal();
|
||||||
|
|
||||||
|
if (this[_signal]) {
|
||||||
abortSignal.follow(newSignal, this[_signal]);
|
abortSignal.follow(newSignal, this[_signal]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this[_flash]) {
|
||||||
return fromInnerRequest(
|
return fromInnerRequest(
|
||||||
newReq,
|
newReq,
|
||||||
newSignal,
|
newSignal,
|
||||||
guardFromHeaders(this[_headers]),
|
guardFromHeaders(this[_headers]),
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromInnerRequest(
|
||||||
|
newReq,
|
||||||
|
newSignal,
|
||||||
|
guardFromHeaders(this[_headers]),
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -573,14 +602,22 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {InnerRequest} inner
|
* @param {InnerRequest} inner
|
||||||
|
* @param {AbortSignal} signal
|
||||||
* @param {"request" | "immutable" | "request-no-cors" | "response" | "none"} guard
|
* @param {"request" | "immutable" | "request-no-cors" | "response" | "none"} guard
|
||||||
|
* @param {boolean} flash
|
||||||
* @returns {Request}
|
* @returns {Request}
|
||||||
*/
|
*/
|
||||||
function fromInnerRequest(inner, signal, guard) {
|
function fromInnerRequest(inner, signal, guard, flash) {
|
||||||
const request = webidl.createBranded(Request);
|
const request = webidl.createBranded(Request);
|
||||||
|
if (flash) {
|
||||||
|
request[_flash] = inner;
|
||||||
|
} else {
|
||||||
request[_request] = inner;
|
request[_request] = inner;
|
||||||
|
}
|
||||||
request[_signal] = signal;
|
request[_signal] = signal;
|
||||||
request[_getHeaders] = () => headersFromHeaderList(inner.headerList, guard);
|
request[_getHeaders] = flash
|
||||||
|
? () => headersFromHeaderList(inner.headerList(), guard)
|
||||||
|
: () => headersFromHeaderList(inner.headerList, guard);
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,6 +643,7 @@
|
||||||
body: body !== null ? new InnerBody(body) : null,
|
body: body !== null ? new InnerBody(body) : null,
|
||||||
methodCb,
|
methodCb,
|
||||||
urlCb,
|
urlCb,
|
||||||
|
headerList: headersCb,
|
||||||
streamRid,
|
streamRid,
|
||||||
serverId,
|
serverId,
|
||||||
redirectMode: "follow",
|
redirectMode: "follow",
|
||||||
|
|
2
ext/fetch/internal.d.ts
vendored
2
ext/fetch/internal.d.ts
vendored
|
@ -83,6 +83,8 @@ declare namespace globalThis {
|
||||||
| "request-no-cors"
|
| "request-no-cors"
|
||||||
| "response"
|
| "response"
|
||||||
| "none",
|
| "none",
|
||||||
|
skipBody: boolean,
|
||||||
|
flash: boolean,
|
||||||
): Request;
|
): Request;
|
||||||
function redirectStatus(status: number): boolean;
|
function redirectStatus(status: number): boolean;
|
||||||
function nullBodyStatus(status: number): boolean;
|
function nullBodyStatus(status: number): boolean;
|
||||||
|
|
|
@ -135,7 +135,12 @@
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
const signal = abortSignal.newSignal();
|
const signal = abortSignal.newSignal();
|
||||||
const request = fromInnerRequest(innerRequest, signal, "immutable");
|
const request = fromInnerRequest(
|
||||||
|
innerRequest,
|
||||||
|
signal,
|
||||||
|
"immutable",
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
const respondWith = createRespondWith(
|
const respondWith = createRespondWith(
|
||||||
this,
|
this,
|
||||||
|
|
Loading…
Add table
Reference in a new issue