Compare commits

...

1 Commits

Author SHA1 Message Date
Claude Bot
c40089e6e1 fix(http): add destroySoon to HTTP upgrade sockets
The NodeHTTPServerSocket class used in HTTP upgrade events was missing
the destroySoon method that exists on net.Socket, breaking libraries
like Vite's WebSocket proxy that rely on this method.

Closes #24127

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 21:59:53 +00:00
2 changed files with 62 additions and 0 deletions

View File

@@ -1105,6 +1105,13 @@ const NodeHTTPServerSocket = class Socket extends Duplex {
get [kInternalSocketData]() {
return this[kHandle]?.response;
}
// https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/lib/net.js#L785
destroySoon() {
if (this.writable) this.end();
if (this.writableFinished) this.destroy();
else this.once("finish", this.destroy);
}
} as unknown as typeof import("node:net").Socket;
function _writeHead(statusCode, reason, obj, response) {

View File

@@ -0,0 +1,55 @@
import { expect, test } from "bun:test";
import { bunEnv, bunExe } from "harness";
// https://github.com/oven-sh/bun/issues/24127
// socket.destroySoon() is missing from HTTP server upgrade sockets
test("HTTP upgrade socket has destroySoon method", async () => {
await using proc = Bun.spawn({
cmd: [
bunExe(),
"-e",
`
const http = require("node:http");
const server = http.createServer();
server.on("upgrade", (req, socket, head) => {
console.log("destroySoon type:", typeof socket.destroySoon);
if (typeof socket.destroySoon === "function") {
socket.destroySoon();
console.log("destroySoon called successfully");
} else {
console.log("ERROR: destroySoon is not a function");
process.exit(1);
}
server.close(() => process.exit(0));
});
server.listen(0, "127.0.0.1", () => {
const addr = server.address();
const req = http.request({
hostname: "127.0.0.1",
port: addr.port,
path: "/ws",
method: "GET",
headers: {
"Upgrade": "websocket",
"Connection": "Upgrade",
"Sec-WebSocket-Key": "dGhlIHNhbXBsZSBub25jZQ==",
"Sec-WebSocket-Version": "13"
}
});
req.end();
});
setTimeout(() => process.exit(1), 5000);
`,
],
env: bunEnv,
stdout: "pipe",
stderr: "pipe",
});
const [stdout, stderr, exitCode] = await Promise.all([proc.stdout.text(), proc.stderr.text(), proc.exited]);
expect(stdout).toContain("destroySoon type: function");
expect(stdout).toContain("destroySoon called successfully");
expect(stderr).toBe("");
expect(exitCode).toBe(0);
});