0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

fix(ext/http): abort request signal when response errors (#17822)

This commit is contained in:
Timo Wilhelm 2023-03-15 23:37:06 +01:00 committed by GitHub
parent 1c285ac214
commit 92c3ac3034
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 3 deletions

View file

@ -2762,6 +2762,39 @@ for (const compression of [true, false]) {
}); });
} }
Deno.test({
name: "request signal is aborted when response errors",
permissions: { net: true },
async fn() {
let httpConn: Deno.HttpConn;
const promise = (async () => {
const listener = Deno.listen({ port: 4501 });
const conn = await listener.accept();
listener.close();
httpConn = Deno.serveHttp(conn);
const ev = await httpConn.nextRequest();
const { request, respondWith } = ev!;
await delay(300);
await assertRejects(() => respondWith(new Response("Hello World")));
assert(request.signal.aborted);
})();
const abortController = new AbortController();
fetch("http://127.0.0.1:4501/", {
signal: abortController.signal,
}).catch(() => {
// ignore
});
await delay(100);
abortController.abort();
await promise;
httpConn!.close();
},
});
function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader { function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
// Based on https://tools.ietf.org/html/rfc2616#section-19.4.6 // Based on https://tools.ietf.org/html/rfc2616#section-19.4.6
const tp = new TextProtoReader(r); const tp = new TextProtoReader(r);

View file

@ -18,7 +18,7 @@ import {
fromInnerRequest, fromInnerRequest,
newInnerRequest, newInnerRequest,
} from "ext:deno_fetch/23_request.js"; } from "ext:deno_fetch/23_request.js";
import * as abortSignal from "ext:deno_web/03_abort_signal.js"; import { AbortController } from "ext:deno_web/03_abort_signal.js";
import { import {
_eventLoop, _eventLoop,
_idleTimeoutDuration, _idleTimeoutDuration,
@ -135,10 +135,10 @@ class HttpConn {
body !== null ? new InnerBody(body) : null, body !== null ? new InnerBody(body) : null,
false, false,
); );
const signal = abortSignal.newSignal(); const abortController = new AbortController();
const request = fromInnerRequest( const request = fromInnerRequest(
innerRequest, innerRequest,
signal, abortController.signal,
"immutable", "immutable",
false, false,
); );
@ -149,6 +149,7 @@ class HttpConn {
request, request,
this.#remoteAddr, this.#remoteAddr,
this.#localAddr, this.#localAddr,
abortController,
); );
return { request, respondWith }; return { request, respondWith };
@ -185,6 +186,7 @@ function createRespondWith(
request, request,
remoteAddr, remoteAddr,
localAddr, localAddr,
abortController,
) { ) {
return async function respondWith(resp) { return async function respondWith(resp) {
try { try {
@ -381,6 +383,9 @@ function createRespondWith(
} }
ws[_serverHandleIdleTimeout](); ws[_serverHandleIdleTimeout]();
} }
} catch (error) {
abortController.abort(error);
throw error;
} finally { } finally {
if (SetPrototypeDelete(httpConn.managedResources, streamRid)) { if (SetPrototypeDelete(httpConn.managedResources, streamRid)) {
core.close(streamRid); core.close(streamRid);