Skip to content

Commit 032f8d0

Browse files
satyarohithsbmsr
authored andcommitted
fix(ext/node): ignore stream error during enqueue (denoland#24243)
1 parent 0f7d617 commit 032f8d0

File tree

2 files changed

+57
-4
lines changed

2 files changed

+57
-4
lines changed

ext/node/polyfills/http.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,10 +1346,14 @@ export class ServerResponse extends NodeWritable {
13461346
#socketOverride: any | null = null;
13471347

13481348
static #enqueue(controller: ReadableStreamDefaultController, chunk: Chunk) {
1349-
if (typeof chunk === "string") {
1350-
controller.enqueue(ENCODER.encode(chunk));
1351-
} else {
1352-
controller.enqueue(chunk);
1349+
try {
1350+
if (typeof chunk === "string") {
1351+
controller.enqueue(ENCODER.encode(chunk));
1352+
} else {
1353+
controller.enqueue(chunk);
1354+
}
1355+
} catch (_) {
1356+
// The stream might have been closed. Ignore the error.
13531357
}
13541358
}
13551359

tests/unit_node/http_test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1130,3 +1130,52 @@ Deno.test("[node/http] server closeIdleConnections shutdown", async () => {
11301130

11311131
await promise;
11321132
});
1133+
1134+
Deno.test("[node/http] client closing a streaming response doesn't terminate server", async () => {
1135+
let interval: number;
1136+
const server = http.createServer((req, res) => {
1137+
res.writeHead(200, { "Content-Type": "text/plain" });
1138+
interval = setInterval(() => {
1139+
res.write("Hello, world!\n");
1140+
}, 100);
1141+
req.on("end", () => {
1142+
clearInterval(interval);
1143+
res.end();
1144+
});
1145+
req.on("error", (err) => {
1146+
console.error("Request error:", err);
1147+
clearInterval(interval);
1148+
res.end();
1149+
});
1150+
});
1151+
1152+
const deferred1 = Promise.withResolvers<void>();
1153+
server.listen(0, () => {
1154+
// deno-lint-ignore no-explicit-any
1155+
const port = (server.address() as any).port;
1156+
1157+
// Create a client connection to the server
1158+
const client = net.createConnection({ port }, () => {
1159+
console.log("Client connected to server");
1160+
1161+
// Write data to the server
1162+
client.write("GET / HTTP/1.1\r\n");
1163+
client.write("Host: localhost\r\n");
1164+
client.write("Connection: close\r\n");
1165+
client.write("\r\n");
1166+
1167+
// End the client connection prematurely while reading data
1168+
client.on("data", (data) => {
1169+
assert(data.length > 0);
1170+
client.end();
1171+
setTimeout(() => deferred1.resolve(), 100);
1172+
});
1173+
});
1174+
});
1175+
1176+
await deferred1.promise;
1177+
assertEquals(server.listening, true);
1178+
server.close();
1179+
assertEquals(server.listening, false);
1180+
clearInterval(interval!);
1181+
});

0 commit comments

Comments
 (0)