Cross-runtime HTTP servers using WHATWG request and response primitives.
Serving is supported on Node, Deno, and Bun. Browser bundles can import the
package and use its constants and MIME resolver, but http.serve throws
because browsers cannot listen for incoming HTTP connections.
import http from "@rcompat/http";
import type {
Actions, Conf, Method, Serve, Server, Timeout, ValidStatus, WebSocket,
WebSocketData, WebSocketInput,
} from "@rcompat/http";The default HTTP server utility aggregate.
http.methods#
Supported lowercase HTTP method names.
http.methods: readonly ["get", "post", "put", "delete", "head", "connect", "options", "trace", "patch"];http.MIME#
Common MIME types keyed by uppercase names.
http.MIME: {
readonly APPLICATION_GZIP: "application/gzip";
readonly APPLICATION_JSON: "application/json";
readonly APPLICATION_LD_JSON: "application/ld+json";
readonly APPLICATION_MANIFEST_JSON: "application/manifest+json";
readonly APPLICATION_OCTET_STREAM: "application/octet-stream";
readonly APPLICATION_PDF: "application/pdf";
readonly APPLICATION_RSS_XML: "application/rss+xml";
readonly APPLICATION_WASM: "application/wasm";
readonly APPLICATION_X_7Z_COMPRESSED: "application/x-7z-compressed";
readonly APPLICATION_X_BZIP2: "application/x-bzip2";
readonly APPLICATION_X_RAR_COMPRESSED: "application/x-rar-compressed";
readonly APPLICATION_X_TAR: "application/x-tar";
readonly APPLICATION_X_WWW_FORM_URLENCODED: "application/x-www-form-urlencoded";
readonly APPLICATION_XML: "application/xml";
readonly APPLICATION_YAML: "application/yaml";
readonly APPLICATION_ZIP: "application/zip";
readonly AUDIO_MPEG: "audio/mpeg";
readonly AUDIO_OGG: "audio/ogg";
readonly AUDIO_WAV: "audio/wav";
readonly AUDIO_WEBM: "audio/webm";
readonly FONT_OTF: "font/otf";
readonly FONT_TTF: "font/ttf";
readonly FONT_WOFF: "font/woff";
readonly FONT_WOFF2: "font/woff2";
readonly IMAGE_APNG: "image/apng";
readonly IMAGE_AVIF: "image/avif";
readonly IMAGE_BMP: "image/bmp";
readonly IMAGE_GIF: "image/gif";
readonly IMAGE_JPEG: "image/jpeg";
readonly IMAGE_PNG: "image/png";
readonly IMAGE_SVG_XML: "image/svg+xml";
readonly IMAGE_TIFF: "image/tiff";
readonly IMAGE_WEBP: "image/webp";
readonly IMAGE_X_ICON: "image/x-icon";
readonly MULTIPART_FORM_DATA: "multipart/form-data";
readonly TEXT_CSS: "text/css";
readonly TEXT_CSV: "text/csv";
readonly TEXT_EVENT_STREAM: "text/event-stream";
readonly TEXT_HTML: "text/html";
readonly TEXT_JAVASCRIPT: "text/javascript";
readonly TEXT_MARKDOWN: "text/markdown";
readonly TEXT_PLAIN: "text/plain";
readonly TEXT_RTF: "text/rtf";
readonly TEXT_TAB_SEPARATED_VALUES: "text/tab-separated-values";
readonly TEXT_VTT: "text/vtt";
readonly VIDEO_MP2T: "video/mp2t";
readonly VIDEO_MP4: "video/mp4";
readonly VIDEO_OGG: "video/ogg";
readonly VIDEO_QUICKTIME: "video/quicktime";
readonly VIDEO_WEBM: "video/webm";
};http.Status#
Standard HTTP status codes keyed by uppercase names.
http.Status: {
readonly ACCEPTED: 202;
readonly ALREADY_REPORTED: 208;
readonly BAD_GATEWAY: 502;
readonly BAD_REQUEST: 400;
readonly CONFLICT: 409;
readonly CONTINUE: 100;
readonly CREATED: 201;
readonly EARLY_HINTS: 103;
readonly EXPECTATION_FAILED: 417;
readonly FAILED_DEPENDENCY: 424;
readonly FORBIDDEN: 403;
readonly FOUND: 302;
readonly GATEWAY_TIMEOUT: 504;
readonly GONE: 410;
readonly HTTP_VERSION_NOT_SUPPORTED: 505;
readonly IM_A_TEAPOT: 418;
readonly IM_USED: 226;
readonly INSUFFICIENT_STORAGE: 507;
readonly INTERNAL_SERVER_ERROR: 500;
readonly LENGTH_REQUIRED: 411;
readonly LOCKED: 423;
readonly LOOP_DETECTED: 508;
readonly METHOD_NOT_ALLOWED: 405;
readonly MISDIRECTED_REQUEST: 421;
readonly MOVED_PERMANENTLY: 301;
readonly MULTIPLE_CHOICES: 300;
readonly NETWORK_AUTHENTICATION_REQUIRED: 511;
readonly NO_CONTENT: 204;
readonly NON_AUTHORITATIVE_INFORMATION: 203;
readonly NOT_ACCEPTABLE: 406;
readonly NOT_EXTENDED: 510;
readonly NOT_FOUND: 404;
readonly NOT_IMPLEMENTED: 501;
readonly NOT_MODIFIED: 304;
readonly OK: 200;
readonly PARTIAL_CONTENT: 206;
readonly PAYLOAD_TOO_LARGE: 413;
readonly PAYMENT_REQUIRED: 402;
readonly PERMANENT_REDIRECT: 308;
readonly PRECONDITION_FAILED: 412;
readonly PRECONDITION_REQUIRED: 428;
readonly PROCESS: 102;
readonly PROXY_AUTHENTICATION_REQUIRED: 407;
readonly RANGE_NOT_SATISFIABLE: 416;
readonly REQUEST_HEADER_FIELDS_TOO_LARGE: 431;
readonly REQUEST_TIMEOUT: 408;
readonly RESET_CONTENT: 205;
readonly SEE_OTHER: 303;
readonly SERVICE_UNAVAILABLE: 503;
readonly SWITCH_PROXY: 306;
readonly SWITCHING_PROTOCOLS: 101;
readonly TEMPORARY_REDIRECT: 307;
readonly TOO_EARLY: 425;
readonly TOO_MANY_REQUESTS: 429;
readonly UNAUTHORIZED: 401;
readonly UNAVAILABLE_FOR_LEGAL_REASONS: 451;
readonly UNPROCESSABLE_ENTITY: 422;
readonly UNSUPPORTED_MEDIA_TYPE: 415;
readonly UPGRADE_REQUIRED: 426;
readonly URI_TOO_LONG: 414;
readonly USE_PROXY: 305;
readonly VARIANT_ALSO_NEGOTIATES: 506;
};http.toMIME()#
Resolves a filename extension to a MIME type.
Parameters
filename— Filename or path whose final extension is resolved.
Returns: The matching MIME type, or application/octet-stream when the
extension is absent or unknown.
http.toMIME(filename: string): string;http.serve()#
Starts a runtime-native HTTP server.
Parameters
handler— Incoming request handler.conf— Listening, TLS, and timeout configuration.
Returns: A promise for the running server controls.
Throws: In browsers, where listening for HTTP connections is unavailable.
Example
const server = await http.serve(
() => new Response("Hello"),
{ port: 8080 },
);
server.stop();Types#
Actions#
WebSocket lifecycle callbacks.
interface Actions extends Dict {
// Called when a socket closes.
close?: (socket: WebSocket, code: number, reason: string) => unknown;
// Called with a text string or binary byte array.
message?: (socket: WebSocket, message: WebSocketData) => unknown;
// Called when a socket opens.
open?: (socket: WebSocket) => unknown;
}Conf#
HTTP server configuration.
type Conf = {
// Hostname or address on which to listen.
host: string;
// TCP port on which to listen.
port: number;
// TLS certificate and private key files.
ssl?: {
// Certificate file.
cert: FileRef;
// Private-key file.
key: FileRef;
};
// Portable server timeout policy.
timeout?: Timeout;
};Method#
A lowercase method represented by http.methods.
type Method = "get" | "post" | "put" | "delete" | "head" | "connect" | "options" | "trace" | "patch";Serve#
Starts a runtime-native HTTP server.
Parameters
handler— Incoming request handler.conf— Listening, TLS, and timeout configuration.
Returns: A promise for the running server controls.
Throws: In browsers, where listening for HTTP connections is unavailable.
Example
const server = await http.serve(
() => new Response("Hello"),
{ port: 8080 },
);
server.stop();Server#
A running HTTP server.
type Server = {
// Stops accepting requests and closes the server.
stop(): void;
// Upgrades to WebSocket and returns the runtime response or `null`.
upgrade(request: Request, actions: Actions): null | Response;
};Timeout#
Portable server timeout policy in whole milliseconds.
Omitting the object, using an empty object, or omitting an individual member
preserves the corresponding runtime default. A value of 0 disables a
supported clock.
inactivity is supported by Node and Bun; Bun rounds it up to whole seconds.
It accepts values through 255000. request and headers are Node-only and
accept values through 2147483647. Deno rejects every configured member,
and Bun rejects request and headers, even when the value is 0.
On Node, enabled headers cannot exceed the effective request timeout.
Unknown members, non-integers, negative values, and out-of-range values are
rejected before the server binds.
type Timeout = {
// Maximum consecutive in-flight network inactivity; traffic resets it.
inactivity?: number;
// Maximum total time to receive request headers and body.
request?: number;
// Maximum total time to receive complete request headers.
headers?: number;
};ValidStatus#
A numeric status represented by http.Status.
type ValidStatus = typeof http.Status[keyof typeof http.Status];WebSocket#
Portable server-side WebSocket.
Node limits each assembled incoming or outgoing message to 16 MiB, caps queued outgoing data at 32 MiB, does not negotiate extensions, and selects the first offered subprotocol.
interface WebSocket {
// Bytes currently waiting to be written, when reported by the runtime.
readonly bufferedAmount?: number;
// Negotiated subprotocol, when reported by the runtime.
readonly protocol?: string;
// Current WebSocket ready-state number.
readonly readyState: number;
// Closes the connection with an optional close code and reason.
close(code?: number, reason?: string): void;
// Sends text, an array buffer, or bytes.
send(data: WebSocketInput): void;
}WebSocketData#
Portable incoming WebSocket message data.
type WebSocketData = string | Uint8Array;WebSocketInput#
Portable outgoing WebSocket message data.
type WebSocketInput = string | ArrayBuffer | Uint8Array;Supporting contract#
Handler#
Handles an incoming request and optionally produces a response.
Node supplies its request-compatible adapter; Deno and Bun supply a
native WHATWG Request.
type Handler = (request: PseudoRequest | Request) =>
MaybePromise<null | Response>;