From 72f815515ad6a1739fe3a20dd6d21334583b6098 Mon Sep 17 00:00:00 2001 From: BennyFranciscus <268274351+BennyFranciscus@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:52:50 +0000 Subject: [PATCH 1/2] Add Elysia: Bun-native TypeScript framework (~18k stars) --- frameworks/elysia/Dockerfile | 8 ++ frameworks/elysia/entrypoint.sh | 6 ++ frameworks/elysia/meta.json | 21 ++++ frameworks/elysia/package.json | 7 ++ frameworks/elysia/server.ts | 183 ++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+) create mode 100644 frameworks/elysia/Dockerfile create mode 100644 frameworks/elysia/entrypoint.sh create mode 100644 frameworks/elysia/meta.json create mode 100644 frameworks/elysia/package.json create mode 100644 frameworks/elysia/server.ts diff --git a/frameworks/elysia/Dockerfile b/frameworks/elysia/Dockerfile new file mode 100644 index 00000000..bc0da0af --- /dev/null +++ b/frameworks/elysia/Dockerfile @@ -0,0 +1,8 @@ +FROM oven/bun:latest +WORKDIR /app +COPY package.json ./ +RUN bun install --production +COPY server.ts entrypoint.sh ./ +RUN chmod +x entrypoint.sh +EXPOSE 8080 8443 +CMD ["/app/entrypoint.sh"] diff --git a/frameworks/elysia/entrypoint.sh b/frameworks/elysia/entrypoint.sh new file mode 100644 index 00000000..0a30f973 --- /dev/null +++ b/frameworks/elysia/entrypoint.sh @@ -0,0 +1,6 @@ +#!/bin/sh +CPUS=$(nproc) +for i in $(seq 1 "$CPUS"); do + bun run /app/server.ts & +done +wait diff --git a/frameworks/elysia/meta.json b/frameworks/elysia/meta.json new file mode 100644 index 00000000..4b9487bb --- /dev/null +++ b/frameworks/elysia/meta.json @@ -0,0 +1,21 @@ +{ + "display_name": "Elysia", + "language": "TS", + "type": "framework", + "engine": "JSC", + "description": "Ergonomic TypeScript framework built for Bun with end-to-end type safety and excellent DX.", + "repo": "https://github.com/elysiajs/elysia", + "enabled": true, + "tests": [ + "baseline", + "pipelined", + "limited-conn", + "json", + "upload", + "compression", + "noisy", + "mixed", + "baseline-h2", + "static-h2" + ] +} diff --git a/frameworks/elysia/package.json b/frameworks/elysia/package.json new file mode 100644 index 00000000..1f099f41 --- /dev/null +++ b/frameworks/elysia/package.json @@ -0,0 +1,7 @@ +{ + "name": "httparena-elysia", + "private": true, + "dependencies": { + "elysia": "^1.4.0" + } +} diff --git a/frameworks/elysia/server.ts b/frameworks/elysia/server.ts new file mode 100644 index 00000000..5c234258 --- /dev/null +++ b/frameworks/elysia/server.ts @@ -0,0 +1,183 @@ +import { Elysia } from "elysia"; +import { Database } from "bun:sqlite"; +import { readFileSync, readdirSync, existsSync } from "fs"; + +const MIME_TYPES: Record = { + ".css": "text/css", ".js": "application/javascript", ".html": "text/html", + ".woff2": "font/woff2", ".svg": "image/svg+xml", ".webp": "image/webp", ".json": "application/json", +}; + +// Load datasets +const datasetItems: any[] = JSON.parse(readFileSync("/data/dataset.json", "utf8")); + +const largeData = JSON.parse(readFileSync("/data/dataset-large.json", "utf8")); +const largeItems = largeData.map((d: any) => ({ + id: d.id, name: d.name, category: d.category, + price: d.price, quantity: d.quantity, active: d.active, + tags: d.tags, rating: d.rating, + total: Math.round(d.price * d.quantity * 100) / 100, +})); +const largeJsonBuf = Buffer.from(JSON.stringify({ items: largeItems, count: largeItems.length })); + +// Open SQLite database read-only +let dbStmt: any = null; +for (let attempt = 0; attempt < 3 && !dbStmt; attempt++) { + try { + const db = new Database("/data/benchmark.db", { readonly: true }); + db.exec("PRAGMA mmap_size=268435456"); + dbStmt = db.prepare("SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN ? AND ? LIMIT 50"); + } catch (e) { + console.error(`SQLite open attempt ${attempt + 1} failed:`, e); + if (attempt < 2) Bun.sleepSync(50); + } +} + +// Pre-load static files +const staticFiles: Record = {}; +try { + for (const name of readdirSync("/data/static")) { + const buf = readFileSync(`/data/static/${name}`); + const ext = name.slice(name.lastIndexOf(".")); + staticFiles[name] = { buf: Buffer.from(buf), ct: MIME_TYPES[ext] || "application/octet-stream" }; + } +} catch (_) {} + +function sumQuery(url: string): number { + const q = url.indexOf("?"); + if (q === -1) return 0; + let sum = 0; + const qs = url.slice(q + 1); + let i = 0; + while (i < qs.length) { + const eq = qs.indexOf("=", i); + if (eq === -1) break; + let amp = qs.indexOf("&", eq); + if (amp === -1) amp = qs.length; + const n = parseInt(qs.slice(eq + 1, amp), 10); + if (!isNaN(n)) sum += n; + i = amp + 1; + } + return sum; +} + +// Read TLS certs +let tlsOptions: { cert: string; key: string } | undefined; +try { + tlsOptions = { + cert: readFileSync("/certs/server.crt", "utf8"), + key: readFileSync("/certs/server.key", "utf8"), + }; +} catch (_) {} + +// Build route handlers as a reusable plugin +function addRoutes(app: Elysia) { + return app + .get("/pipeline", () => new Response("ok", { headers: { "content-type": "text/plain" } })) + + .get("/baseline2", ({ request }) => { + const body = String(sumQuery(request.url)); + return new Response(body, { headers: { "content-type": "text/plain" } }); + }) + + .all("/baseline11", async ({ request }) => { + const querySum = sumQuery(request.url); + if (request.method === "POST") { + const body = await request.text(); + let total = querySum; + const n = parseInt(body.trim(), 10); + if (!isNaN(n)) total += n; + return new Response(String(total), { headers: { "content-type": "text/plain" } }); + } + return new Response(String(querySum), { headers: { "content-type": "text/plain" } }); + }) + + .get("/json", () => { + const items = datasetItems.map((d: any) => ({ + id: d.id, name: d.name, category: d.category, + price: d.price, quantity: d.quantity, active: d.active, + tags: d.tags, rating: d.rating, + total: Math.round(d.price * d.quantity * 100) / 100, + })); + const body = JSON.stringify({ items, count: items.length }); + return new Response(body, { + headers: { "content-type": "application/json", "content-length": String(Buffer.byteLength(body)) }, + }); + }) + + .get("/compression", () => { + const compressed = Bun.gzipSync(largeJsonBuf, { level: 1 }); + return new Response(compressed, { + headers: { + "content-type": "application/json", + "content-encoding": "gzip", + "content-length": String(compressed.length), + }, + }); + }) + + .get("/db", ({ request }) => { + if (!dbStmt) return new Response("DB not available", { status: 500 }); + try { + let min = 10, max = 50; + const url = request.url; + const qIdx = url.indexOf("?"); + if (qIdx !== -1) { + const qs = url.slice(qIdx + 1); + for (const pair of qs.split("&")) { + const eq = pair.indexOf("="); + if (eq === -1) continue; + const k = pair.slice(0, eq), v = pair.slice(eq + 1); + if (k === "min") min = parseFloat(v) || 10; + else if (k === "max") max = parseFloat(v) || 50; + } + } + const rows = dbStmt.all(min, max) as any[]; + const items = rows.map((r: any) => ({ + id: r.id, name: r.name, category: r.category, + price: r.price, quantity: r.quantity, active: r.active === 1, + tags: JSON.parse(r.tags), + rating: { score: r.rating_score, count: r.rating_count }, + })); + const body = JSON.stringify({ items, count: items.length }); + return new Response(body, { + headers: { "content-type": "application/json", "content-length": String(Buffer.byteLength(body)) }, + }); + } catch (e: any) { + return new Response(e.message || "db error", { status: 500 }); + } + }) + + .post("/upload", async ({ request }) => { + const ab = await request.arrayBuffer(); + return new Response(String(ab.byteLength), { + headers: { "content-type": "text/plain" }, + }); + }) + + .get("/static/:filename", ({ params: { filename } }) => { + const sf = staticFiles[filename]; + if (sf) { + return new Response(sf.buf, { + headers: { "content-type": sf.ct, "content-length": String(sf.buf.length) }, + }); + } + return new Response("Not found", { status: 404 }); + }) + + // Catch-all for unknown routes + .all("*", () => new Response("Not found", { status: 404 })); +} + +// HTTP server on port 8080 +const httpApp = addRoutes(new Elysia()); +httpApp.listen({ port: 8080, reusePort: true }); + +// HTTPS/H2 server on port 8443 +if (tlsOptions) { + const httpsApp = addRoutes(new Elysia()); + httpsApp.listen({ + port: 8443, + reusePort: true, + tls: tlsOptions, + }); +} From 996c804b709a3189b1b796daa6e0291cf1cac6bb Mon Sep 17 00:00:00 2001 From: BennyFranciscus <268274351+BennyFranciscus@users.noreply.github.com> Date: Fri, 20 Mar 2026 18:55:59 +0000 Subject: [PATCH 2/2] =?UTF-8?q?fix(elysia):=20drop=20noisy/H2=20tests=20?= =?UTF-8?q?=E2=80=94=20Bun=20lacks=20HTTP/2=20server=20support,=20drops=20?= =?UTF-8?q?bad-method=20connections?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove baseline-h2, static-h2, noisy from test list - Remove TLS/HTTPS server code (not needed without H2 tests) - Clean up unused imports --- frameworks/elysia/meta.json | 5 +---- frameworks/elysia/server.ts | 26 +------------------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/frameworks/elysia/meta.json b/frameworks/elysia/meta.json index 4b9487bb..8346ccc6 100644 --- a/frameworks/elysia/meta.json +++ b/frameworks/elysia/meta.json @@ -13,9 +13,6 @@ "json", "upload", "compression", - "noisy", - "mixed", - "baseline-h2", - "static-h2" + "mixed" ] } diff --git a/frameworks/elysia/server.ts b/frameworks/elysia/server.ts index 5c234258..cf150b6f 100644 --- a/frameworks/elysia/server.ts +++ b/frameworks/elysia/server.ts @@ -1,6 +1,6 @@ import { Elysia } from "elysia"; import { Database } from "bun:sqlite"; -import { readFileSync, readdirSync, existsSync } from "fs"; +import { readFileSync, readdirSync } from "fs"; const MIME_TYPES: Record = { ".css": "text/css", ".js": "application/javascript", ".html": "text/html", @@ -60,25 +60,11 @@ function sumQuery(url: string): number { return sum; } -// Read TLS certs -let tlsOptions: { cert: string; key: string } | undefined; -try { - tlsOptions = { - cert: readFileSync("/certs/server.crt", "utf8"), - key: readFileSync("/certs/server.key", "utf8"), - }; -} catch (_) {} - // Build route handlers as a reusable plugin function addRoutes(app: Elysia) { return app .get("/pipeline", () => new Response("ok", { headers: { "content-type": "text/plain" } })) - .get("/baseline2", ({ request }) => { - const body = String(sumQuery(request.url)); - return new Response(body, { headers: { "content-type": "text/plain" } }); - }) - .all("/baseline11", async ({ request }) => { const querySum = sumQuery(request.url); if (request.method === "POST") { @@ -171,13 +157,3 @@ function addRoutes(app: Elysia) { // HTTP server on port 8080 const httpApp = addRoutes(new Elysia()); httpApp.listen({ port: 8080, reusePort: true }); - -// HTTPS/H2 server on port 8443 -if (tlsOptions) { - const httpsApp = addRoutes(new Elysia()); - httpsApp.listen({ - port: 8443, - reusePort: true, - tls: tlsOptions, - }); -}