Skip to content

Commit

Permalink
switching protocol (101) on Upgrade request
Browse files Browse the repository at this point in the history
  • Loading branch information
Mastercuber committed Dec 14, 2023
1 parent 129a3f8 commit 35fe367
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 13 deletions.
53 changes: 42 additions & 11 deletions src/listen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
} from "node:http2";
import { promisify } from "node:util";
import type { AddressInfo } from "node:net";
import { createServer as createRawTcpIpcServer } from "node:net";
import { getPort } from "get-port-please";
import addShutdown from "http-shutdown";
import consola from "consola";
Expand Down Expand Up @@ -138,6 +139,14 @@ export async function listen(
let https: Listener["https"] = false;
const httpsOptions = listhenOptions.https as HTTPSOptions;
let _addr: AddressInfo;

async function bind() {
// @ts-ignore
await promisify(server.listen.bind(server))(port, listhenOptions.hostname);
_addr = server.address() as AddressInfo;
listhenOptions.port = _addr.port;
}

if (httpsOptions) {
https = await resolveCertificate(httpsOptions);
server = listhenOptions.http2
Expand All @@ -150,19 +159,40 @@ export async function listen(
)
: createHttpsServer(https, handle as RequestListenerHttp1x);
addShutdown(server);
// @ts-ignore
await promisify(server.listen.bind(server))(port, listhenOptions.hostname);
_addr = server.address() as AddressInfo;
listhenOptions.port = _addr.port;
await bind();
} else if (listhenOptions.http2) {
const h1Server = createHttpServer((req, res) => {
if (req.headers.upgrade === "h2c") {
res.writeHead(101, {
Upgrade: "h2c",
Connection: "Upgrade",
});
res.flushHeaders();
// TODO Headers are flushed to the client, but it seems as the connection is not passed to the h2Server
h2Server.emit("connection", req, res.socket);
}
(handle as RequestListenerHttp1x)(req, res);
});
const h2Server = createHttp2Server(handle as RequestListenerHttp2);
server = createRawTcpIpcServer(async (socket) => {
const chunk = await new Promise((resolve) =>
socket.once("data", resolve),
);
// @ts-expect-error
socket._readableState.flowing = undefined;
socket.unshift(chunk);
if ((chunk as any).toString("utf8", 0, 3) === "PRI") {
h2Server.emit("connection", socket);
} else {
h1Server.emit("connection", socket);
}
});
addShutdown(server);
await bind();
} else {
server = listhenOptions.http2
? createHttp2Server(handle as RequestListenerHttp2)
: createHttpServer(handle as RequestListenerHttp1x);
server = createHttpServer(handle as RequestListenerHttp1x);
addShutdown(server);
// @ts-ignore
await promisify(server.listen.bind(server))(port, listhenOptions.hostname);
_addr = server.address() as AddressInfo;
listhenOptions.port = _addr.port;
await bind();
}

// --- GetURL Utility ---
Expand Down Expand Up @@ -322,6 +352,7 @@ export async function listen(
url: getURL(),
https,
server,
// @ts-ignore
address: _addr,
open: _open,
showURL,
Expand Down
9 changes: 7 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import type { Server as HttpServer } from "node:http";
import type { Server as HttpsServer } from "node:https";
import type { Http2Server, Http2SecureServer } from "node:http2";
import type { AddressInfo } from "node:net";
import type { AddressInfo, Server as RawTcpIpcServer } from "node:net";
import type { GetPortInput } from "get-port-please";

export type Server = HttpServer | HttpsServer | Http2Server | Http2SecureServer;
export type Server =
| HttpServer
| HttpsServer
| Http2Server
| Http2SecureServer
| RawTcpIpcServer;

export interface Certificate {
key: string;
Expand Down

0 comments on commit 35fe367

Please sign in to comment.