diff --git a/src/listen.ts b/src/listen.ts index a552525..3382a32 100644 --- a/src/listen.ts +++ b/src/listen.ts @@ -1,8 +1,10 @@ -import { createServer } from "node:http"; -import type { Server as HTTPServer } from "node:https"; -import { createServer as createHTTPSServer } from "node:https"; +import { createServer, IncomingMessage, ServerResponse } from "node:http"; +import { + createSecureServer, + Http2ServerRequest, + Http2ServerResponse, +} from "node:http2"; import { promisify } from "node:util"; -import type { RequestListener, Server } from "node:http"; import type { AddressInfo } from "node:net"; import { getPort } from "get-port-please"; import addShutdown from "http-shutdown"; @@ -19,6 +21,7 @@ import type { HTTPSOptions, ListenURL, GetURLOptions, + Server, } from "./types"; import { formatURL, @@ -34,6 +37,22 @@ import { resolveCertificate } from "./_cert"; import { isWsl } from "./lib/wsl"; import { isDocker } from "./lib/docker"; +type RequestListenerHttp1x< + Request extends typeof IncomingMessage = typeof IncomingMessage, + Response extends + typeof ServerResponse = typeof ServerResponse, +> = ( + req: InstanceType, + res: InstanceType & { req: InstanceType }, +) => void; + +type RequestListenerHttp2< + Request extends typeof Http2ServerRequest = typeof Http2ServerRequest, + Response extends typeof Http2ServerResponse = typeof Http2ServerResponse, +> = (request: InstanceType, response: InstanceType) => void; + +type RequestListener = RequestListenerHttp1x | RequestListenerHttp2; + export async function listen( handle: RequestListener, _options: Partial = {}, @@ -108,20 +127,26 @@ export async function listen( })); // --- Listen --- - let server: Server | HTTPServer; + let server: Server; let https: Listener["https"] = false; const httpsOptions = listhenOptions.https as HTTPSOptions; let _addr: AddressInfo; if (httpsOptions) { https = await resolveCertificate(httpsOptions); - server = createHTTPSServer(https, handle); + server = createSecureServer( + { + ...https, + allowHTTP1: true, + }, + handle as RequestListenerHttp2, + ); addShutdown(server); // @ts-ignore await promisify(server.listen.bind(server))(port, listhenOptions.hostname); _addr = server.address() as AddressInfo; listhenOptions.port = _addr.port; } else { - server = createServer(handle); + server = createServer(handle as RequestListenerHttp1x); addShutdown(server); // @ts-ignore await promisify(server.listen.bind(server))(port, listhenOptions.hostname); diff --git a/src/server/dev.ts b/src/server/dev.ts index fed2437..23755af 100644 --- a/src/server/dev.ts +++ b/src/server/dev.ts @@ -1,5 +1,7 @@ import { existsSync, statSync } from "node:fs"; import { readFile, stat } from "node:fs/promises"; +import { Http2ServerRequest, Http2ServerResponse } from "node:http2"; +import { IncomingMessage, ServerResponse } from "node:http"; import { consola } from "consola"; import { dirname, join, resolve } from "pathe"; import type { ConsolaInstance } from "consola"; @@ -12,6 +14,11 @@ export interface DevServerOptions { logger?: ConsolaInstance; } +type NodeListener = ( + req: IncomingMessage | Http2ServerRequest, + res: ServerResponse | Http2ServerResponse, +) => void; + export async function createDevServer( entry: string, options: DevServerOptions, @@ -151,7 +158,7 @@ export async function createDevServer( return { cwd, resolver, - nodeListener: toNodeListener(app), + nodeListener: toNodeListener(app) as NodeListener, reload: (_initial?: boolean) => loadHandle(_initial), _entry: resolveEntry(), }; diff --git a/src/types.ts b/src/types.ts index ea68f5e..263ab98 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,8 +1,11 @@ -import type { Server } from "node:http"; -import type { Server as HTTPServer } from "node:https"; -import { AddressInfo } from "node:net"; +import type { Server as HttpServer } from "node:http"; +import type { Server as HttpsServer } from "node:https"; +import type { Http2SecureServer } from "node:http2"; +import type { AddressInfo } from "node:net"; import type { GetPortInput } from "get-port-please"; +export type Server = HttpServer | HttpsServer | Http2SecureServer; + export interface Certificate { key: string; cert: string; @@ -72,7 +75,7 @@ export interface ListenURL { export interface Listener { url: string; address: AddressInfo; - server: Server | HTTPServer; + server: Server; https: false | Certificate; close: () => Promise; open: () => Promise;