Server Options
When starting a new server, in addition to main fetch handler, you can provide additional options to customize listening server.
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!"),
});
There are two kind of options:
- Generic options: Top level options are intended to have exactly same functionality regardless of runtime
- Runtime specific: Allow customizing more runtime specific options
Generic Options
port
The port server should be listening to.
Default is value of PORT environment variable or 3000.
0 to use a random port.hostname
The hostname (IP or resolvable host) server listener should bound to.
When not provided, server will listen to all network interfaces by default.
localhost.reusePort
Enabling this option allows multiple processes to bind to the same port, which is useful for load balancing.
exclusive flag enabled by default, srvx uses non-exclusive mode for consistency.silent
If enabled, no server listening message will be printed (enabled by default when TEST environment variable is set).
protocol
The protocol to use for the server.
Possible values are http or https.
If protocol is not set, Server will use http as the default protocol or https if both tls.cert and tls.key options are provided.
tls
TLS server options.
Example:
import { serve } from "srvx";
serve({
tls: { cert: "./server.crt", key: "./server.key" },
fetch: () => new Response("๐ Hello there!"),
});
Options:
cert: Path or inline content for the certificate in PEM format (required).key: Path or inline content for the private key in PEM format (required).passphrase: Passphrase for the private key (optional).
cert and key values in PEM format starting with -----BEGIN .Client certificates (mutual TLS) are available through the mtls() plugin.
onError
Runtime agnostic error handler.
Example:
import { serve } from "srvx";
serve({
fetch: () => new Response("๐ Hello there!"),
onError(error) {
return new Response(`<pre>${error}\n${error.stack}</pre>`, {
headers: { "Content-Type": "text/html" },
});
},
});
maxRequestBodySize
Maximum allowed size in bytes for the request body. Defaults to undefined (no limit).
As the body is read, its accumulated length is tracked and, once it exceeds the limit, reading is aborted and rejects with a 413-style error. The error carries statusCode: 413, status: 413 and code: "ERR_BODY_TOO_LARGE", so a handler (or onError) can map it to an HTTP 413 Payload Too Large response.
The limit covers both buffered reads (request.text() / request.json()) and the streamed body (request.body, and therefore request.arrayBuffer() / .blob() / .bytes() / .formData()).
Example:
import { serve } from "srvx";
serve({
maxRequestBodySize: 1024 * 1024, // 1 MiB
fetch: async (request) => {
try {
return Response.json(await request.json());
} catch (error) {
if (error.code === "ERR_BODY_TOO_LARGE") {
return new Response("Payload Too Large", { status: 413 });
}
throw error;
}
},
});
- Node: enforced by srvx (the request body stream is size-limited).
- Bun: forwarded to Bun's native
maxRequestBodySize, enforced by Bun (responds with413before the handler runs). - Deno: enforced by srvx (
Deno.servehas no native option).
trustProxy
Whether to trust X-Forwarded-* headers (X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-For, and the HTTP/2 :scheme) when deriving request.url and request.ip. Defaults to false.
Any client can send X-Forwarded-Proto: https, X-Forwarded-Host or X-Forwarded-For, so trusting them lets a request masquerade as https:, forge its host, or spoof its client IP. Only enable this when a proxy you control sits in front and overwrites the headers.
false(default): ignore the headers; use the real connection protocol, the on-the-wireHostheader and the socket peer address.true: always trust the headers."loopback": trust them only when the proxy connects from a loopback address (127.0.0.0/8or::1).string[]: trust them only when the proxy's address is in the list.
Example:
import { serve } from "srvx";
serve({
// Behind a reverse proxy you control (e.g. Nginx, a load balancer):
trustProxy: true,
fetch: (request) => new Response(new URL(request.url).protocol),
});
Runtime Specific Options
Node.js
Example:
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!"),
});
Bun
Example:
import { serve } from "srvx";
serve({
bun: {
error(error) {
return new Response(`<pre>${error}\n${error.stack}</pre>`, {
headers: { "Content-Type": "text/html" },
});
},
},
fetch: () => new Response("๐ Hello there!"),
});
Deno
Example:
import { serve } from "srvx";
serve({
deno: {
onError(error) {
return new Response(`<pre>${error}\n${error.stack}</pre>`, {
headers: { "Content-Type": "text/html" },
});
},
},
fetch: () => new Response("๐ Hello there!"),
});