mirror of
https://github.com/oven-sh/bun
synced 2026-02-12 03:48:56 +00:00
### What does this PR do? handle socket upgrade in NodeHTTP.cpp ### How did you verify your code works? Run the test added with asan it should catch the bug --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
51 lines
1.9 KiB
TypeScript
51 lines
1.9 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { tls as options } from "harness";
|
|
import https from "https";
|
|
import type { AddressInfo } from "node:net";
|
|
import tls from "tls";
|
|
import { WebSocketServer } from "ws";
|
|
test("should not crash when closing sockets after upgrade", async () => {
|
|
const { promise, resolve } = Promise.withResolvers();
|
|
let http_sockets: tls.TLSSocket[] = [];
|
|
|
|
const server = https.createServer(options, (req, res) => {
|
|
http_sockets.push(res.socket as tls.TLSSocket);
|
|
res.writeHead(200, { "Content-Type": "text/plain", "Connection": "Keep-Alive" });
|
|
res.end("okay");
|
|
res.detachSocket(res.socket!);
|
|
});
|
|
|
|
server.listen(0, "127.0.0.1", () => {
|
|
const wsServer = new WebSocketServer({ server });
|
|
wsServer.on("connection", socket => {});
|
|
|
|
const port = (server.address() as AddressInfo).port;
|
|
const socket = tls.connect({ port, ca: options.cert }, () => {
|
|
// normal request keep the socket alive
|
|
socket.write(`GET / HTTP/1.1\r\nHost: localhost:${port}\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n`);
|
|
socket.write(`GET / HTTP/1.1\r\nHost: localhost:${port}\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n`);
|
|
socket.write(`GET / HTTP/1.1\r\nHost: localhost:${port}\r\nConnection: Keep-Alive\r\nContent-Length: 0\r\n\r\n`);
|
|
// upgrade to websocket
|
|
socket.write(
|
|
`GET / HTTP/1.1\r\nHost: localhost:${port}\r\nConnection: Upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n`,
|
|
);
|
|
});
|
|
socket.on("data", data => {
|
|
const isWebSocket = data?.toString().includes("Upgrade: websocket");
|
|
if (isWebSocket) {
|
|
socket.destroy();
|
|
setTimeout(() => {
|
|
http_sockets.forEach(http_socket => {
|
|
http_socket?.destroy();
|
|
});
|
|
server.closeAllConnections();
|
|
resolve();
|
|
}, 10);
|
|
}
|
|
});
|
|
});
|
|
|
|
await promise;
|
|
expect().pass();
|
|
});
|