0
0
Fork 0
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:
Isaiah Gamble 2023-01-14 23:08:34 -05:00 committed by Bartek Iwańczuk
parent e989882162
commit d731f1bf35
No known key found for this signature in database
GPG key ID: 0C6BCDDC3B3AD750
4 changed files with 91 additions and 7 deletions

View file

@ -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(

View file

@ -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",

View file

@ -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;

View file

@ -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,