### Create and Start a Server with srvx Source: https://context7.com/h3js/srvx/llms.txt Use the `serve()` function to create a server instance with a fetch handler and configuration. The server starts listening asynchronously. Use `server.ready()` to wait for the server to be bound and `server.url` to get the listening address. ```typescript import { serve } from "srvx"; const server = serve({ port: 3000, hostname: "localhost", fetch(request) { const url = new URL(request.url); if (url.pathname === "/health") { return Response.json({ status: "ok" }); } if (url.pathname === "/echo" && request.method === "POST") { return new Response(request.body, { headers: { "Content-Type": request.headers.get("Content-Type") || "text/plain" }, }); } return new Response("Not Found", { status: 404 }); }, }); await server.ready(); console.log(`Server listening at ${server.url}`); // → Server listening at http://localhost:3000 // Graceful shutdown // await server.close(); // Force-close all active connections immediately // await server.close(true); ``` -------------------------------- ### Start and Control a Server Instance Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Starts a server and returns an instance to control its lifecycle. Use this to access server properties and manage its readiness. ```js import { serve } from "srvx"; const server = serve({ fetch(request) { return new Response(`🔥 Server is powered by ${server.runtime}.`); }, }); await server.ready(); console.log(`🚀 Server is ready at ${server.url}`); // When server is no longer needed // await server.close(true /* closeActiveConnections */) ``` -------------------------------- ### Start development server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Start the srvx development server using a specific entry file. ```bash srvx serve --entry ./server.ts ``` -------------------------------- ### serve(options) Source: https://context7.com/h3js/srvx/llms.txt The primary entry point for creating and starting an HTTP server. It accepts a ServerOptions object with a required fetch handler and optional configuration. The server begins listening asynchronously after this function is called. ```APIDOC ## serve(options) — Create and start a server The primary entry point. Accepts a `ServerOptions` object with a required `fetch` handler and optional configuration. Returns a `Server` instance immediately; the server begins listening asynchronously. ```ts import { serve } from "srvx"; const server = serve({ port: 3000, hostname: "localhost", fetch(request) { const url = new URL(request.url); if (url.pathname === "/health") { return Response.json({ status: "ok" }); } if (url.pathname === "/echo" && request.method === "POST") { return new Response(request.body, { headers: { "Content-Type": request.headers.get("Content-Type") || "text/plain" }, }); } return new Response("Not Found", { status: 404 }); }, }); await server.ready(); console.log(`Server listening at ${server.url}`); // → Server listening at http://localhost:3000 // Graceful shutdown // await server.close(); // Force-close all active connections immediately // await server.close(true); ``` ``` -------------------------------- ### Create a Deno HTTP Server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/7.node.md This example shows how to create an HTTP server using Deno's 'Deno.serve' API. It listens on port 3000 and returns a 'Hello, Deno!' response. ```js Deno.serve({ port: 3000 }, (_req, info) => new Response("Hello, Deno!")); ``` -------------------------------- ### Create a Bun HTTP Server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/7.node.md This example demonstrates how to create an HTTP server using Bun's 'Bun.serve' API. It listens on port 3000 and handles requests by returning a 'Hello, Bun!' response. ```js Bun.serve({ port: 3000, fetch: (req) => new Response("Hello, Bun!") }); ``` -------------------------------- ### Configure Server Options with TLS and Error Handling Source: https://context7.com/h3js/srvx/llms.txt This example demonstrates configuring server options including port, hostname, TLS certificates, and a universal error handler. It also shows runtime-specific options for Node.js and Bun. ```typescript import { serve } from "srvx"; serve({ port: 8443, hostname: "0.0.0.0", reusePort: true, // allow multiple processes on the same port silent: false, // TLS / HTTPS tls: { cert: "./certs/server.crt", // path or inline PEM starting with "-----BEGIN " key: "./certs/server.key", passphrase: process.env.TLS_PASSPHRASE, }, // Universal error handler onError(error) { console.error("Unhandled server error:", error); return new Response( JSON.stringify({ error: String(error) }), { status: 500, headers: { "Content-Type": "application/json" } }, ); }, // Graceful shutdown with custom timeouts gracefulShutdown: { gracefulTimeout: 5000, forceTimeout: 10000 }, // Node.js-specific: double max header size, enable HTTP/2 node: { maxHeaderSize: 32768, http2: true }, // Bun-specific override bun: { development: false }, fetch: () => new Response("Secure server running!"), }); ``` -------------------------------- ### Fetch using a specific entry file Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Fetch data from a server started with a specific entry file, overriding the default. ```bash srvx fetch --entry ./server.ts /api/users ``` -------------------------------- ### Configure Node.js Server Options Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/5.options.md Provides an example of customizing Node.js specific server options, such as `maxHeadersize` and `ipv6Only`. Refer to Node.js documentation for a full list. ```js import { serve } from "srvx"; serve({ node: { maxHeadersize: 16384 * 2, // Double default ipv6Only: true, // Disable dual-stack support // http2: false // Disable http2 support (enabled by default in TLS mode) }, fetch: () => new Response("👋 Hello there!"), }); ``` -------------------------------- ### Start production server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Start the srvx server in production mode. This typically disables watch mode and debugging. ```bash srvx serve --prod ``` -------------------------------- ### Create a Simple Node.js HTTP Server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/7.node.md This example demonstrates how to create a basic HTTP server using Node.js's built-in 'node:http' module. It listens on port 3000 and responds with 'Hello, Node.js!' to all incoming requests. ```js import { createServer } from "node:http"; createServer((req, res) => { res.end("Hello, Node.js!"); }).listen(3000); ``` -------------------------------- ### Running srvx Server Source: https://github.com/h3js/srvx/blob/main/README.md Commands to run the srvx server using different package managers and runtimes. Ensure you have the respective runtime or package manager installed. ```bash # Node.js $ npx srvx # npm $ pnpx srvx # pnpm $ yarn dlx srvx # yarn # Deno $ deno -A npm:srvx # Bun $ bunx --bun srvx ``` -------------------------------- ### Enable Diagnostics Channel Tracing with tracingPlugin Source: https://context7.com/h3js/srvx/llms.txt Integrate APM tools or custom logging by subscribing to SRVX diagnostics channels. Ensure subscriptions are set up before starting the server. ```typescript import { serve } from "srvx"; import { tracingPlugin } from "srvx/tracing"; import { tracingChannel } from "node:diagnostics_channel"; // Subscribe to tracing channels before starting the server tracingChannel("srvx.request").subscribe({ start: () => {}, end: () => {}, asyncStart: ({ request }) => console.log(`[req:start] ${request.method} ${request.url}`), asyncEnd: ({ result }) => console.log(`[req:end] status=${result?.status}`), error: ({ error }) => console.error(`[req:error]`, error), }); tracingChannel("srvx.middleware").subscribe({ start: () => {}, end: () => {}, asyncStart: ({ request }) => console.log(`[mw:start] ${request.url}`), asyncEnd: ({ result }) => console.log(`[mw:end] status=${result?.status}`), error: ({ error }) => console.error(`[mw:error]`, error), }); serve({ plugins: [tracingPlugin()], middleware: [ async (req, next) => { const res = await next(); res.headers.set("X-Powered-By", "srvx"); return res; }, ], fetch(req) { return Response.json({ path: new URL(req.url).pathname }); }, }); ``` -------------------------------- ### Directly Calling Server Handler Source: https://github.com/h3js/srvx/blob/main/README.md Use the `srvx fetch` command to directly invoke your server handler without starting a full server instance. This is useful for testing or specific API calls. ```bash $ npx srvx fetch /api/users ``` -------------------------------- ### Serve with Generic and Runtime Options Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/5.options.md Illustrates how to configure a server with both generic options like port and hostname, and runtime-specific options for Node.js, Bun, or Deno. ```js import { serve } from "srvx"; serve({ // Generic options port: 3000, hostname: "localhost", // Runtime specific options node: {}, bun: {}, deno: {}, // Main server handler fetch: () => new Response("👋 Hello there!"), }); ``` -------------------------------- ### Run Server with CLI (Deno) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using Deno. ```bash deno -A npm:srvx ``` -------------------------------- ### Initialize and Mount Petite-Vue App Source: https://github.com/h3js/srvx/blob/main/examples/websocket/public/index.html Sets up the reactive store, defines WebSocket connection logic, message formatting, and mounts the Petite-Vue application. Ensure the script is loaded after the DOM is ready. ```javascript import { createApp, reactive, nextTick } from "https://esm.sh/petite-vue@0.4.1"; let ws; const store = reactive({ message: "", messages: [], }); const scroll = () => { nextTick(() => { const el = document.querySelector("#messages"); el.scrollTop = el.scrollHeight; el.scrollTo({ top: el.scrollHeight, behavior: "smooth", }); }); }; const format = async () => { for (const message of store.messages) { if (!message._fmt && message.text.startsWith("{")) { message._fmt = true; const { codeToHtml } = await import("https://esm.sh/shiki@1.0.0"); const str = JSON.stringify(JSON.parse(message.text), null, 2); message.formattedText = await codeToHtml(str, { lang: "json", theme: "dark-plus", }); } } }; const log = (user, ...args) => { console.log("[ws]", user, ...args); store.messages.push({ text: args.join(" "), formattedText: "", user: user, date: new Date().toLocaleString(), }); scroll(); format(); }; const connect = async () => { const isSecure = location.protocol === "https:"; const url = (isSecure ? "wss://" : "ws://") + location.host + "/_ws"; if (ws) { log("ws", "Closing previous connection before reconnecting..."); ws.close(); clear(); } log("ws", "Connecting to", url, "..."); ws = new WebSocket(url); ws.addEventListener("message", async (event) => { let data = typeof event.data === "string" ? event.data : await event.data.text(); const { user = "system", message = "" } = data.startsWith("{") ? JSON.parse(data) : { message: data }; log(user, typeof message === "string" ? message : JSON.stringify(message)); }); await new Promise((resolve) => ws.addEventListener("open", resolve)); log("ws", "Connected!"); }; const clear = () => { store.messages.splice(0, store.messages.length); log("system", "previous messages cleared"); }; const send = () => { console.log("sending message..."); if (store.message) { ws.send(store.message); } store.message = ""; }; const ping = () => { log("ws", "Sending ping"); ws.send("ping"); }; createApp({ store, send, ping, clear, connect, rand: Math.random(), }).mount(); await connect(); ``` -------------------------------- ### Run Server with CLI (Bun) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using Bun. ```bash bunx --bun srvx ``` -------------------------------- ### server.ready() / server.close() Source: https://context7.com/h3js/srvx/llms.txt Methods to manage the server's lifecycle. `ready()` returns a promise that resolves when the server is fully bound and accepting connections. `close()` stops accepting new connections, with an option to immediately tear down in-flight connections. ```APIDOC ## server.ready() / server.close() — Server lifecycle `ready()` returns a promise that resolves when the server is fully bound and accepting connections. `close()` stops accepting new connections; pass `true` to immediately tear down in-flight connections. ```ts import { serve } from "srvx"; const server = serve({ port: 0, // random available port fetch: () => Response.json({ hello: "world" }), }); // Wait until port is bound before sending requests await server.ready(); console.log(`Listening on port ${server.port} → ${server.url}`); // Register a background task at server level (outside request handlers) server.waitUntil?.( fetch("https://telemetry.example.com", { method: "POST", body: JSON.stringify({ event: "server_started", url: server.url }), }), ); // In tests or scripts, shut down cleanly process.on("SIGINT", async () => { await server.close(); console.log("Server stopped."); process.exit(0); }); ``` ``` -------------------------------- ### Create a Server Entry (API) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Define a server entry point using the srvx API. This method allows direct import of the `serve` function. ```js import { serve } from "srvx"; const server = serve({ fetch(request) { return Response.json({ hello: "world!" }); }, }); ``` -------------------------------- ### Run Server with CLI (npm) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using npm. ```bash npx srvx ``` -------------------------------- ### Configure TLS Server Options Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/5.options.md Shows how to enable HTTPS by providing certificate and key paths within the `tls` option. Ensure private keys are kept secure. ```js import { serve } from "srvx"; serve({ tls: { cert: "./server.crt", key: "./server.key" }, fetch: () => new Response("👋 Hello there!"), }); ``` -------------------------------- ### Fetch from default entry Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Fetch data from the default server entry point using the srvx fetch command. ```bash srvx fetch ``` -------------------------------- ### Run Server with API (Bun) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using Bun. ```bash bun run server.mjs ``` -------------------------------- ### Run Server with API (Deno) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using Deno. ```bash deno run --allow-env --allow-net server.mjs ``` -------------------------------- ### Run Server with CLI (pnpm) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using pnpm. ```bash pnpx srvx ``` -------------------------------- ### Wait for Server to be Ready Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Await the server to be listening to the port and ready to accept connections. ```js await server.ready(); ``` -------------------------------- ### Run Server with CLI (yarn) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using yarn. ```bash yarn dlx srvx ``` -------------------------------- ### Create a Server Entry (CLI) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Define a server entry point for the srvx CLI. This function will handle incoming requests. ```js export default { fetch(req: Request) { return Response.json({ hello: "world!" }); }, }; ``` -------------------------------- ### Enable JITI loader Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Use the --import option to preload a loader like jiti for enhanced module loading capabilities. ```bash srvx serve --import=jiti/register ``` -------------------------------- ### Run Server with API (Node.js) Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/1.index.md Execute the srvx server using Node.js. ```bash node server.mjs ``` -------------------------------- ### Configure Bun Server Options Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/5.options.md Shows how to configure Bun-specific options, including a custom error handler. Consult the Bun HTTP documentation for all available settings. ```js import { serve } from "srvx"; serve({ bun: { error(error) { return new Response(`
${error}\n${error.stack}
`, { headers: { "Content-Type": "text/html" }, }); }, }, fetch: () => new Response("👋 Hello there!"), }); ``` -------------------------------- ### SRVX CLI Commands for Serving and Fetching Source: https://context7.com/h3js/srvx/llms.txt Utilize the SRVX CLI for development and production server management, static file serving, and direct request testing. ```bash # Start dev server with file watching (default entry: server.ts) npx srvx serve --entry ./server.ts --port 3000 ``` ```bash # Start production server (no watcher, no debug output) npx srvx serve --prod --port 8080 --host localhost ``` ```bash # HTTPS/HTTP2 with TLS npx srvx serve --tls --cert ./cert.pem --key ./key.pem --port 443 ``` ```bash # Serve static files from ./public alongside your handler npx srvx serve --static ./public ``` ```bash # Run via Deno deno -A npm:srvx serve --entry ./server.ts ``` ```bash # Run via Bun bunx --bun srvx serve --entry ./server.ts ``` ```bash # Test a specific route without starting a network server npx srvx fetch /api/users ``` ```bash # POST with JSON body npx srvx fetch -X POST -H "Content-Type: application/json" -d '{"name":"Alice"}' /api/users ``` ```bash # Verbose output (show request and response headers) npx srvx fetch -v /api/users ``` ```bash # Pipe body from stdin echo '{"name":"Bob"}' | npx srvx fetch -d @- -X POST /api/users ``` ```bash # Show version info npx srvx --version ``` -------------------------------- ### Server Methods Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Methods to manage the server's readiness and shutdown process. ```APIDOC ## Server Methods ### `server.ready()` Returns a promise that will be resolved when server is listening to the port and ready to accept connections. **Example:** ```js await server.ready(); ``` ### `server.close(closeActiveConnections?)` Stop listening to prevent new connections from being accepted. By default, calling `close` does not cancel in-flight requests or websockets. That means it may take some time before all network activity stops. If `closeActiveConnections` is set to `true`, it will immediately terminate in-flight requests, websockets, and stop accepting new connections. **Example:** ```js // Stop accepting new requests await server.close(); // Stop accepting new requests and cancel all current connections await server.close(true); ``` ``` -------------------------------- ### Configure Deno Server Options Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/5.options.md Illustrates configuring Deno-specific server options, including a custom `onError` handler. Refer to Deno's serve API documentation for comprehensive options. ```js import { serve } from "srvx"; serve({ deno: { onError(error) { return new Response(`
${error}\n${error.stack}
`, { headers: { "Content-Type": "text/html" }, }); }, }, fetch: () => new Response("👋 Hello there!"), }); ``` -------------------------------- ### Manage Server Lifecycle with ready() and close() Source: https://context7.com/h3js/srvx/llms.txt Use `server.ready()` to await server binding and `server.close()` to shut down the server gracefully. `server.waitUntil()` can be used to register background tasks at the server level. Handle signals like `SIGINT` for clean shutdowns. ```typescript import { serve } from "srvx"; const server = serve({ port: 0, // random available port fetch: () => Response.json({ hello: "world" }), }); // Wait until port is bound before sending requests await server.ready(); console.log(`Listening on port ${server.port} → ${server.url}`); // Register a background task at server level (outside request handlers) server.waitUntil?.( fetch("https://telemetry.example.com", { method: "POST", body: JSON.stringify({ event: "server_started", url: server.url }), }), ); // In tests or scripts, shut down cleanly process.on("SIGINT", async () => { await server.close(); console.log("Server stopped."); process.exit(0); }); ``` -------------------------------- ### Run Node.js Benchmarks Source: https://github.com/h3js/srvx/blob/main/test/bench-node/README.md Execute all Node.js compatibility benchmarks using pnpm. This command initiates a comprehensive performance test suite. ```sh pnpm run bench:node --all ``` -------------------------------- ### Enable TLS for HTTPS/HTTP2 Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Configure the srvx server to use TLS by providing certificate and key files for secure connections. ```bash srvx serve --tls --cert=cert.pem --key=key.pem ``` -------------------------------- ### Register Background Task with Server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Register a background task that the server should await before closing. This is useful for tasks that need to complete before the server shuts down. ```js import { serve } from "srvx"; const server = serve({ fetch: (request) => new Response("OK"), }); const promise = fetch("https://telemetry.example.com", { method: "POST", body: JSON.stringify({ event: "server_started" }), }); server.waitUntil?.(promise); ``` -------------------------------- ### Access to the Underlying Server Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Advanced usage to access the underlying server instance provided by the runtime environment (Bun, Deno, Node.js). ```APIDOC ## Access to the Underlying Server > [!NOTE] > srvx tries to translate most common options to op level properties. This is only for advanced usage. ### `server.bun.server` Access to the underlying Bun server instance when running in Bun. :read-more{to="https://bun.sh/docs/api/http"} ### `server.deno.server` Access to the underlying Bun server instance when running in Deno. :read-more{to="https://docs.deno.com/api/deno/~/Deno.HttpServer"} ### `server.node.server` Access to the underlying Node.js server instance when running in Node.js :read-more{to="https://nodejs.org/api/http.html#class-httpserver"} ``` -------------------------------- ### Serve Static Files with srvx/static Source: https://context7.com/h3js/srvx/llms.txt This middleware factory serves files from a specified directory with automatic MIME type detection and compression. It can also transform HTML content before serving. ```typescript import { serve } from "srvx"; import { serveStatic } from "srvx/static"; serve({ middleware: [ serveStatic({ dir: "./public", // directory to serve methods: ["GET", "HEAD"], // default // Optional: transform HTML before serving (e.g., inject SSR data) renderHTML({ request, html, filename }) { const enhanced = html.replace( "", ``, ); return new Response(enhanced, { headers: { "Content-Type": "text/html" } }); }, }), ], fetch(req) { // Reached only if no static file matched return new Response("Not Found", { status: 404 }); }, }); // File layout: // public/ // index.html → served at GET / // app.js → served at GET /app.js (with gzip/br if supported) // logo.png → served at GET /logo.png ``` -------------------------------- ### Perform a POST request Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Execute an HTTP POST request to a specific server path using srvx fetch. ```bash srvx fetch -X POST /api/users ``` -------------------------------- ### Serve with FastResponse and FastURL in Node.js Source: https://context7.com/h3js/srvx/llms.txt Utilizes FastResponse for optimized Node.js responses and FastURL for lazy URL parsing. Import from 'srvx'. ```typescript import { serve, FastResponse, FastURL } from "srvx"; serve({ port: 3000, fetch(req) { // FastURL: parse only what you need, lazily const url = new FastURL(req.url); if (url.pathname === "/ping") { // FastResponse: ~94% faster than `new Response(...)` on Node.js return new FastResponse("pong", { status: 200, headers: { "Content-Type": "text/plain" }, }); } const id = url.searchParams.get("id"); return new FastResponse(JSON.stringify({ id }), { headers: { "Content-Type": "application/json" }, }); }, }); ``` -------------------------------- ### Fetch a specific URL path Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Fetch data from a specific path within the server using the srvx fetch command. ```bash srvx fetch /api/users ``` -------------------------------- ### Listen on a specific port Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Configure the srvx server to listen on a custom port. ```bash srvx serve --port=8080 ``` -------------------------------- ### Default srvx Import Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/6.bundler.md Import srvx using the default import. This automatically resolves the correct entrypoint for Node.js, Deno, Cloudflare, and Bun via ESM conditions. ```javascript import { serve } from "srvx"; ``` -------------------------------- ### AWS Lambda Handler with Static Serving Source: https://context7.com/h3js/srvx/llms.txt Wraps ServerOptions into an AWS Lambda handler compatible with API Gateway v1/v2, including static file serving. Import from 'srvx/aws-lambda' and 'srvx/static'. ```typescript import { toLambdaHandler, invokeLambdaHandler } from "srvx/aws-lambda"; import { serveStatic } from "srvx/static"; // Production export for AWS Lambda export const handler = toLambdaHandler({ middleware: [serveStatic({ dir: "public" })], fetch(req: Request) { const url = new URL(req.url); if (url.pathname === "/api/users") { return Response.json([{ id: 1, name: "Alice" }]); } return new Response("Not Found", { status: 404 }); }, }); // Local testing without deploying to AWS const testResponse = await invokeLambdaHandler( handler, new Request("https://example.execute-api.us-east-1.amazonaws.com/api/users"), ); console.log(await testResponse.json()); // → [{ id: 1, name: "Alice" }] ``` -------------------------------- ### Implement WebSocket Server with crossws Plugin Source: https://context7.com/h3js/srvx/llms.txt Register the crossws plugin to handle WebSocket connections. The HTTP fetch handler should return a 426 status for non-WebSocket requests. Ensure correct imports for srvx and the crossws plugin. ```typescript import { serve } from "srvx"; import { plugin as ws } from "crossws/server"; const rooms = new Map>(); serve({ port: 3000, plugins: [ ws({ open(peer) { const room = peer.url?.searchParams.get("room") ?? "general"; if (!rooms.has(room)) rooms.set(room, new Set()); rooms.get(room)!.add(peer); peer.send(JSON.stringify({ system: `Welcome to #${room}` })); }, message(peer, message) { const text = message.text(); if (text === "ping") { peer.send("pong"); return; } // Broadcast to all peers in the same room const room = peer.url?.searchParams.get("room") ?? "general"; for (const other of rooms.get(room) ?? []) { (other as typeof peer).send(JSON.stringify({ from: String(peer), text })); } }, close(peer) { for (const members of rooms.values()) members.delete(peer); }, error(peer, err) { console.error("WS error", peer, err); }, }), ], fetch(req) { return new Response("Connect via WebSocket", { status: 426 }); }, }); ``` -------------------------------- ### toLambdaHandler() / invokeLambdaHandler() Source: https://context7.com/h3js/srvx/llms.txt Adapt your srvx fetch handlers for AWS Lambda or test them locally using `toLambdaHandler` and `invokeLambdaHandler`. ```APIDOC ## `toLambdaHandler(options)` / `invokeLambdaHandler()` — AWS Lambda adapter `toLambdaHandler` from `srvx/aws-lambda` wraps a `ServerOptions` object into an AWS Lambda handler compatible with API Gateway v1/v2. `invokeLambdaHandler` lets you test Lambda handlers locally using standard `Request`/`Response` objects. ```ts import { toLambdaHandler, invokeLambdaHandler } from "srvx/aws-lambda"; import { serveStatic } from "srvx/static"; // Production export for AWS Lambda export const handler = toLambdaHandler({ middleware: [serveStatic({ dir: "public" })], fetch(req: Request) { const url = new URL(req.url); if (url.pathname === "/api/users") { return Response.json([{ id: 1, name: "Alice" }]); } return new Response("Not Found", { status: 404 }); }, }); // Local testing without deploying to AWS const testResponse = await invokeLambdaHandler( handler, new Request("https://example.execute-api.us-east-1.amazonaws.com/api/users"), ); console.log(await testResponse.json()); // → [{ id: 1, name: "Alice" }] ``` ``` -------------------------------- ### Fetch with request body Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Send a request body with a fetch request using the -d option. The data can be a string or read from stdin/file. ```bash srvx fetch -d '{"name":"foo"}' /api ``` -------------------------------- ### Server Properties Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Access to various properties of the server instance for runtime information and control. ```APIDOC ## Server Properties ### `server.options` Access to the sever options set during initialization. :read-more{to="/guide/options"} ### `server.url` Get the computed server listening URL. ### `server.addr` Listening address (hostname or ipv4/ipv6). ### `server.port` Listening port number. :read-more{to="/guide/options#port-required"} ### `server.waitUntil?` Register a background task that the server should await before closing. This is the same function as [`request.waitUntil`](/guide/handler#requestwaituntil) but available at the server level for use outside of request handlers. ```js import { serve } from "srvx"; const server = serve({ fetch: (request) => new Response("OK"), }); const promise = fetch("https://telemetry.example.com", { method: "POST", body: JSON.stringify({ event: "server_started" }), }); server.waitUntil?.(promise); ``` ``` -------------------------------- ### Basic Fetch Handler Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/2.handler.md Defines a basic fetch handler to respond to requests. It returns an HTML response including the request URL and client IP. ```javascript import { serve } from "srvx"; serve({ async fetch(request) { return new Response( `

👋 Hello there

You are visiting ${request.url} from ${request.ip}

`, { headers: { "Content-Type": "text/html" } }, ); }, }); ``` -------------------------------- ### Access Client IP Address Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/2.handler.md Demonstrates accessing the client's IP address using `request.ip`. This is useful for logging or geo-targeting. ```javascript import { serve } from "srvx"; serve({ fetch: (request) => new Response(`Your ip address is "${request.ip}"`), }); ``` -------------------------------- ### Node.js Benchmark Results Source: https://github.com/h3js/srvx/blob/main/test/bench-node/README.md Displays benchmark results for various Node.js HTTP implementations, including native node:http, srvx, whatwg-node, hono, and remix. Results are measured in requests per second (req/sec). ```sh CPU: AMD Ryzen 9 9950X3D Node.js: v24.12.0 OS: linux x64 OHA: 1.12.0 ┌──────────────────┬─────────────────┐ │ node │ '136396 req/sec' │ │ srvx-fast │ '123955 req/sec' │ │ whatwg-node-fast │ '113530 req/sec' │ │ srvx │ '92271 req/sec' │ │ whatwg-node │ '83564 req/sec' │ │ hono-fast │ '55647 req/sec' │ │ hono │ '44563 req/sec' │ │ remix │ '41326 req/sec' │ └──────────────────┴──────────────────┘ ``` -------------------------------- ### Bind to a specific host Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Configure the srvx server to bind to a specific network interface, like localhost. ```bash srvx serve --host=localhost ``` -------------------------------- ### Configure Bundler with ESM Conditions Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/6.bundler.md Manually set the ESM conditions in your bundler configuration to ensure the correct srvx runtime version is resolved during bundling. ```javascript import resolve from "@rollup/plugin-node-resolve"; export default { //... plugins: [ resolve({ preferBuiltins: true, conditions: ["node"], // or "deno", "bun", "workerd", etc. }), ], }; ``` ```typescript import { build } from "esbuild"; await build({ //... conditions: ["node"], // or "deno", "bun", "workerd", etc. }); ``` ```bash esbuild main.ts \ # ... --conditions:node # or deno, bun, workerd, etc. ``` -------------------------------- ### Fetch with custom headers Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Include custom HTTP headers in a fetch request by specifying them with the -H option. ```bash srvx fetch -H "Content-Type: application/json" /api ``` -------------------------------- ### Verbose fetch output Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Enable verbose output for fetch requests to display both request and response headers. ```bash srvx fetch -v /api/users ``` -------------------------------- ### Fetch with body from stdin Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/9.cli.md Pipe data from stdin as the request body for a fetch request, indicated by -d @-. ```bash echo '{"name":"foo"}' | srvx fetch -d @- /api ``` -------------------------------- ### Create AWS Lambda Handler with srvx Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/8.aws-lambda.md Use `toLambdaHandler` to wrap your srvx application for AWS Lambda. Options like `host` and `port` are ignored in this environment. ```typescript import { toLambdaHandler } from "srvx/aws-lambda"; import { serveStatic } from "srvx/static"; export const handler = toLambdaHandler({ middleware: [serveStatic({ dir: "public" })], fetch(req: Request) { return Response.json({ hello: "world!" }); }, }); ``` -------------------------------- ### Convert Node.js Handlers to Fetch Handlers with srvx/node Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/7.node.md Utilize `fetchNodeHandler` or `toFetchHandler` from `srvx/node` to convert Node.js server handlers, such as Express apps, into web fetch handlers. These utilities are designed to run within a Node.js runtime environment. ```javascript import { fetchNodeHandler, toFetchHandler } from "srvx/node"; import express from "express"; const app = express().get("/", (req, res) => { res.send("Hello World!"); }); // Convert express app to a fetch handler const fetchHandler = toFetchHandler(app); const res = await fetchHandler(new Request("http://localhost/")); // Directly fetch express app handler const res = await fetchNodeHandler(app, new Request("http://localhost/")); // 200 OK Hello World! console.log(res.status, res.statusText, await res.text()); ``` -------------------------------- ### Use FastResponse for Improved Performance in Node.js Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/7.node.md Replace the standard `Response` class with `FastResponse` when initializing responses in Node.js to significantly improve performance by avoiding unnecessary internal initializations. This is particularly useful until native Response handling is fully supported in the Node.js http module. ```javascript import { serve, FastResponse } from "srvx"; const server = serve({ port: 3000, fetch() { return new FastResponse("Hello!"); }, }); await server.ready(); console.log(`Server running at ${server.url}`); ``` -------------------------------- ### Implement Custom Error Handling Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/5.options.md Demonstrates how to define a custom `onError` handler to manage and format errors gracefully. This handler overrides built-in error handlers for Deno and Bun. ```js import { serve } from "srvx"; serve({ fetch: () => new Response("👋 Hello there!"), onError(error) { return new Response(`
${error}\n${error.stack}
`, { headers: { "Content-Type": "text/html" }, }); }, }); ``` -------------------------------- ### AWS Lambda streaming - handleLambdaEventWithStream Source: https://context7.com/h3js/srvx/llms.txt Enable streaming responses for large or progressive data on AWS Lambda Function URLs using `handleLambdaEventWithStream`. ```APIDOC ## AWS Lambda streaming — `handleLambdaEventWithStream` For large or progressive responses on Lambda Function URLs, use `handleLambdaEventWithStream` with `awslambda.streamifyResponse()` to stream data as it is produced (up to 20 MB vs 6 MB buffered limit). ```ts import { handleLambdaEventWithStream, type AWSLambdaStreamingHandler } from "srvx/aws-lambda"; async function fetchHandler(request: Request): Promise { const encoder = new TextEncoder(); const stream = new ReadableStream({ async start(controller) { for (const chunk of ["Hello, ", "streaming ", "world!"]) { controller.enqueue(encoder.encode(chunk)); await new Promise((r) => setTimeout(r, 50)); } controller.close(); }, }); return new Response(stream, { headers: { "Content-Type": "text/plain" } }); } // Lambda Function URL with --invoke-mode RESPONSE_STREAM export const handler: AWSLambdaStreamingHandler = awslambda.streamifyResponse( (event, responseStream, context) => handleLambdaEventWithStream(fetchHandler, event, responseStream, context), ); ``` ``` -------------------------------- ### UI Controls Source: https://github.com/h3js/srvx/blob/main/examples/websocket/public/index.html Provides buttons for common WebSocket actions: sending a message, sending a ping, reconnecting, and clearing messages. ```html Send Ping Reconnect Clear ``` -------------------------------- ### Close Server Instance Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/3.server.md Stop listening to prevent new connections. Optionally, terminate in-flight requests and websockets. ```js // Stop accepting new requests await server.close(); ``` ```js // Stop accepting new requests and cancel all current connections await server.close(true); ``` -------------------------------- ### FastResponse and FastURL Source: https://context7.com/h3js/srvx/llms.txt Utilize FastResponse and FastURL for optimized response handling and lazy URL parsing in Node.js applications. ```APIDOC ## `FastResponse` / `FastURL` — Performance primitives for Node.js `FastResponse` is a drop-in `Response` replacement optimized for Node.js that skips heavy internal initialization (e.g., `ReadableStream`, `Headers`) that are not needed for simple Node.js response sending. `FastURL` is a lazy `URL` that defers `pathname` and `searchParams` parsing. ```ts import { serve, FastResponse, FastURL } from "srvx"; serve({ port: 3000, fetch(req) { // FastURL: parse only what you need, lazily const url = new FastURL(req.url); if (url.pathname === "/ping") { // FastResponse: ~94% faster than `new Response(...)` on Node.js return new FastResponse("pong", { status: 200, headers: { "Content-Type": "text/plain" }, }); } const id = url.searchParams.get("id"); return new FastResponse(JSON.stringify({ id }), { headers: { "Content-Type": "application/json" }, }); }, }); ``` ``` -------------------------------- ### Add X-Powered-By Header with Middleware Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/4.middleware.md This middleware adds the 'X-Powered-By: srvx' header to all responses. It's a common pattern for identifying server technology. ```typescript import { serve, type ServerMiddleware, type ServerPlugin } from "srvx"; const xPoweredBy: ServerMiddleware = async (req, next) => { const res = await next(); res.headers.set("X-Powered-By", "srvx"); return res; }; const devLogs: ServerPlugin = (server) => { if (process.env.NODE_ENV === "production") { return; } console.log(`Logger plugin enabled!`); server.options.middleware.push((req, next) => { console.log(`[request] [${req.method}] ${req.url}`); return next(); }); }; serve({ middleware: [xPoweredBy], plugins: [devLogs], fetch(request) { return new Response(`👋 Hello there.`); }, }); ``` -------------------------------- ### Add Response Timing Header Middleware Source: https://context7.com/h3js/srvx/llms.txt This middleware measures and adds an 'X-Response-Time' header to the response. It requires the 'srvx' package. ```typescript import { serve, type ServerMiddleware } from "srvx"; // Middleware: add response timing header const timing: ServerMiddleware = async (req, next) => { const start = Date.now(); const res = await next(); res.headers.set("X-Response-Time", `${Date.now() - start}ms`); return res; }; // Middleware: simple bearer token auth const auth: ServerMiddleware = (req, next) => { const token = req.headers.get("Authorization")?.replace("Bearer ", ""); if (!token || token !== process.env.API_TOKEN) { return new Response("Unauthorized", { status: 401 }); } return next(); }; // Middleware: CORS headers const cors: ServerMiddleware = async (req, next) => { if (req.method === "OPTIONS") { return new Response(null, { status: 204, headers: { "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization", }, }); } const res = await next(); res.headers.set("Access-Control-Allow-Origin", "*"); return res; }; serve({ middleware: [cors, auth, timing], fetch(req) { return Response.json({ message: "Protected resource", url: req.url }); }, }); ``` -------------------------------- ### Displaying Messages Source: https://github.com/h3js/srvx/blob/main/examples/websocket/public/index.html Renders messages from the WebSocket connection. It displays the user, message text, and timestamp. JSON messages are formatted and syntax-highlighted. ```html {{ message.user }} {{ message.text }} {{ message.date }} ``` -------------------------------- ### Background Operation with waitUntil Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/2.handler.md Uses `request.waitUntil` to perform a background operation, such as logging request details to a telemetry service, without blocking the response. ```javascript import { serve } from "srvx"; async function logRequest(request) { await fetch("https://telemetry.example.com", { method: "POST", body: JSON.stringify({ method: request.method, url: request.url, ip: request.ip, }), }); } serve({ fetch: (request) => { request.waitUntil(logRequest(request)); return new Response("OK"); }, }); ``` -------------------------------- ### ServerRequest Source: https://context7.com/h3js/srvx/llms.txt An extended request object passed to the fetch handler. It inherits from the standard Request API and includes additional runtime-specific properties like `ip`, `waitUntil`, `runtime`, and `context`. ```APIDOC ## ServerRequest — Extended request object Every `fetch` handler receives a `ServerRequest` which extends the standard `Request` with additional runtime-specific properties: `ip`, `waitUntil`, `runtime`, and `context`. ```ts import { serve, type ServerRequest } from "srvx"; serve({ async fetch(request: ServerRequest) { // Client IP address (works across all runtimes) const clientIp = request.ip ?? "unknown"; // Arbitrary per-request context (useful with middleware) request.context ??= {}; request.context.startTime = Date.now(); // Fire-and-forget background telemetry without blocking the response request.waitUntil?.( fetch("https://telemetry.example.com/log", { method: "POST", body: JSON.stringify({ ip: clientIp, url: request.url, method: request.method }), }), ); // Access underlying Node.js primitives when running on Node.js if (request.runtime?.name === "node") { const nodeReq = request.runtime.node?.req; console.log("Raw Node.js socket remote address:", nodeReq?.socket?.remoteAddress); } // Access Cloudflare environment bindings when running on Cloudflare Workers if (request.runtime?.name === "cloudflare") { const env = request.runtime.cloudflare?.env as { KV: KVNamespace }; const value = await env.KV.get("some-key"); return Response.json({ value }); } return Response.json({ ip: clientIp, path: new URL(request.url).pathname }); }, }); ``` ``` -------------------------------- ### Configure Bundler to Externalize srvx Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/6.bundler.md Set srvx as an external dependency in your bundler configuration to prevent it from being included in the final bundle. This requires srvx to be available at runtime. ```javascript export default { //... external: ["srvx"], }; ``` ```typescript import { build } from "esbuild"; await build({ //... external: ["srvx"], // Add this }); ``` ```bash esbuild main.ts \ # ... --external:srvx # Add this ``` -------------------------------- ### Node.js Runtime Access Source: https://github.com/h3js/srvx/blob/main/docs/1.guide/2.handler.md Shows how to access underlying Node.js request and response objects via `request.runtime.node` when running in a Node.js environment. This allows for direct manipulation of Node.js specific properties like `res.statusCode`. ```javascript import { serve } from "srvx"; serve({ fetch: (request) => { if (request.runtime.node) { console.log("Node.js req path:", request.runtime.node?.req.path); request.runtime.node.res.statusCode = 418; // I'm a teapot! } return new Response("ok"); }, }); ```