Skip to content

Commit

Permalink
feat: http2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
Mastercuber committed Sep 14, 2023
1 parent c37be8a commit e8988b9
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 12 deletions.
39 changes: 32 additions & 7 deletions src/listen.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -19,6 +21,7 @@ import type {
HTTPSOptions,
ListenURL,
GetURLOptions,
Server,
} from "./types";
import {
formatURL,
Expand All @@ -32,6 +35,22 @@ import {
} from "./_utils";
import { resolveCertificate } from "./_cert";

type RequestListenerHttp1x<
Request extends typeof IncomingMessage = typeof IncomingMessage,
Response extends
typeof ServerResponse<IncomingMessage> = typeof ServerResponse<IncomingMessage>,
> = (
req: InstanceType<Request>,
res: InstanceType<Response> & { req: InstanceType<Request> },
) => void;

type RequestListenerHttp2<
Request extends typeof Http2ServerRequest = typeof Http2ServerRequest,
Response extends typeof Http2ServerResponse = typeof Http2ServerResponse,
> = (request: InstanceType<Request>, response: InstanceType<Response>) => void;

type RequestListener = RequestListenerHttp1x | RequestListenerHttp2;

export async function listen(
handle: RequestListener,
_options: Partial<ListenOptions> = {},
Expand Down Expand Up @@ -106,20 +125,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);
Expand Down
9 changes: 8 additions & 1 deletion src/server/dev.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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,
Expand Down Expand Up @@ -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(),
};
Expand Down
11 changes: 7 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -72,7 +75,7 @@ export interface ListenURL {
export interface Listener {
url: string;
address: AddressInfo;
server: Server | HTTPServer;
server: Server;
https: false | Certificate;
close: () => Promise<void>;
open: () => Promise<void>;
Expand Down

0 comments on commit e8988b9

Please sign in to comment.