Last active
April 3, 2025 21:14
-
-
Save bogeychan/39290d2dcf468389c7b82dd8bdc7b2e0 to your computer and use it in GitHub Desktop.
Basic Bun HTTP2 Adapter for ElysiaJS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// based on https://github.com/elysiajs/elysia/blob/main/src/adapter/bun/index.ts | |
import type { ElysiaAdapter, MaybePromise } from "elysia"; | |
import { BunAdapter } from "elysia/adapter/bun"; | |
import { isNumericString } from "elysia/utils"; | |
import { ReadStream as NodeReadStream } from "node:fs"; | |
import { | |
createSecureServer, | |
type Http2ServerRequest, | |
type Http2ServerResponse, | |
} from "node:http2"; | |
async function onRequest( | |
this: (request: Request) => MaybePromise<Response>, | |
req: Http2ServerRequest, | |
res: Http2ServerResponse | |
) { | |
const { method } = req; | |
const headers: Record<string, string> = {}; | |
for (const name in req.headers) { | |
if (name.startsWith(":")) { | |
continue; | |
} | |
headers[name] = req.headers[name]!.toString(); | |
} | |
const request = new Request( | |
`https://${req.authority ?? "localhost"}${req.url}`, | |
{ | |
headers, | |
method, | |
body: NodeReadStream.toWeb(req) as unknown as ReadableStream<any>, | |
} | |
); | |
let response = this(request); | |
if (response instanceof Promise) { | |
response = await response; | |
} | |
res.statusCode = response.status; | |
response.headers.forEach((value, key) => res.setHeader(key, value)); | |
if (response.body) { | |
NodeReadStream.fromWeb( | |
response.body as unknown as import("stream/web").ReadableStream<any> | |
).pipe(res); | |
} else { | |
res.end(); | |
} | |
} | |
export const HTTP2Adapter: ElysiaAdapter = { | |
...BunAdapter, | |
name: "bun-http2", | |
listen(app) { | |
return (options, callback) => { | |
app.compile(); | |
if (typeof options === "string") { | |
if (!isNumericString(options)) | |
throw new Error("Port must be a numeric value"); | |
options = parseInt(options); | |
} | |
const fetch = app.fetch; | |
// @ts-ignore | |
const { cert, key } = app.config.serve; | |
const server = createSecureServer({ cert, key }, onRequest.bind(fetch)); | |
// @ts-expect-error | |
app.server = { | |
stop() { | |
server?.close(); | |
}, | |
}; | |
function listenerCallback() { | |
if (app.event.start) | |
for (let i = 0; i < app.event.start.length; i++) | |
app.event.start[i].fn(app); | |
if (callback) callback(app.server!); | |
} | |
if (typeof options === "object") { | |
// @ts-ignore | |
const { port, hostname } = options; | |
server.listen(port, hostname, listenerCallback); | |
} else { | |
server.listen(options, listenerCallback); | |
} | |
process.on("beforeExit", () => { | |
if (app.server) { | |
app.server.stop(); | |
app.server = null; | |
if (app.event.stop) | |
for (let i = 0; i < app.event.stop.length; i++) | |
app.event.stop[i].fn(app); | |
} | |
}); | |
// @ts-expect-error private | |
app.promisedModules.then(() => Bun.gc(false)); | |
}; | |
}, | |
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Elysia, t } from "elysia"; | |
import { readFileSync } from "fs"; | |
import { HTTP2Adapter } from "./adapter"; | |
export const app = new Elysia({ | |
adapter: HTTP2Adapter, | |
serve: { | |
cert: readFileSync("./cert.pem", { encoding: "utf8" }), | |
key: readFileSync("./key.pem", { encoding: "utf8" }), | |
}, | |
}) | |
.get("/", "yay") | |
.get("/json", () => ({ my: "json" })) | |
.post("/json", ({ body: { name } }) => `whelp ${name}!`, { | |
body: t.Object({ | |
name: t.String(), | |
}), | |
}) | |
.get("/noop", () => {}) | |
.listen(3000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment