http

js/net/http.ts

fino:net/http — public HTTP API barrel.

This module gathers the stable public HTTP APIs: server helpers (serve, serveHttp), reusable clients (HttpClient, HttpSession, HttpResponse), application routing (App), Server-Sent Events (EventSource), WebSockets (WebSocket, WebSocketConnection), WebTransport, and raw request/response parse and serialize helpers (parseRequest, serializeResponse, and the Arena backing them). Fetch-compatible Headers, Request, and Response are globals and are not re-exported here. Protocol drivers and implementation modules live behind internal:net/http/*.

Import from this barrel when you want the ergonomic entry points without reaching into a specific submodule; the same symbols are also available from their home modules (fino:net/http/server, fino:net/http/client, fino:net/http/app, and so on) when a narrower import is preferable. All the named exports here are re-exports — the symbols are documented in the module that defines them.

import { serveHttp, HttpClient, App } from 'fino:net/http';

// A minimal server: every request gets the same JSON response.
const server = serveHttp({ port: 3000 }, (request) =>
  Response.json({ method: request.method, url: request.url }));

// A pooled client for making outbound requests.
const client = new HttpClient();
const res = await client.fetch('http://127.0.0.1:3000/health');
console.log(res.status, await res.json());

// A routed application when you need middleware and OpenAPI.
const app = new App({ name: 'Example' });
app.get('/hello').handle(() => new Response('hi'));
app.listen({ port: 3001 });

await server.close();

Learn more:

Types

type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'

Re-exported from app.HttpMethod.

type Middleware = (ctx: HttpContext) => HttpHandlerResult | void | Promise<HttpHandlerResult | void>

Re-exported from app.Middleware.

type LayerMiddleware = ( ctx: HttpContext, next: ( ) => Promise<HttpHandlerResult> ) => HttpHandlerResult | void | Promise<HttpHandlerResult | void>

Re-exported from app.LayerMiddleware.

type Handler = (ctx: HttpContext) => HttpHandlerResult | Promise<HttpHandlerResult>

Re-exported from app.Handler.

type WebSocketHandler = (socket: WebSocketConnection, ctx: WebSocketContext) => void | Promise<void>

Re-exported from app.WebSocketHandler.

type WebTransportHandler = (session: WebTransport, ctx: WebTransportContext) => void | Promise<void>

Re-exported from app.WebTransportHandler.

type SseHandler = (events: EventSourceWriter, ctx: SseContext) => void | Promise<void>

Re-exported from app.SseHandler.

type Producer = (ctx: HttpContext) => unknown | Promise<unknown>

Re-exported from app.Producer.

type HttpHandlerResult = Response | WebSocketConnection | WebTransport

Re-exported from js/net/http/server.HttpHandlerResult.

type HttpClientProtocol = 'http/1.1' | 'h2' | 'h3'

Re-exported from js/net/http/client.HttpClientProtocol.

type HttpClientTransport = 'tcp' | 'tls' | 'quic'

Re-exported from js/net/http/client.HttpClientTransport.

type HttpHeadersInit = Headers | string[][] | Record<string, string> | null | undefined

Re-exported from js/net/http/client.HttpHeadersInit.

type HttpSessionEvent = { type: 'connecting'; session: HttpSession; } | { type: 'connected'; session: HttpSession; connection: HttpConnectionInfo; } | { type: 'reconnecting'; session: HttpSession; reason: unknown; } | { type: 'reconnected'; session: HttpSession; connection: HttpConnectionInfo; } | { type: 'closed'; session: HttpSession; reason?: unknown; }

Re-exported from js/net/http/client.HttpSessionEvent.

type HttpProtocol = 'http/1.1' | 'h2' | 'h3'

Re-exported from js/net/http/server.HttpProtocol.

type HttpTransport = 'tcp' | 'tls' | 'quic'

Re-exported from js/net/http/server.HttpTransport.

type HttpRequestHandler = ( request: Request, session: HttpSession ) => HttpHandlerResult | Promise<HttpHandlerResult>

Re-exported from js/net/http/server.HttpRequestHandler.

type HttpTlsPeerInfo = TlsPeerInfo

Re-exported from js/net/http/server.HttpTlsPeerInfo.

type IncomingHttp = IncomingHttpRequest | IncomingWebSocketRequest | IncomingWebTransportRequest

Re-exported from js/net/http/server.IncomingHttp.

type ServerAcceptHandler = (incoming: IncomingHttp, session: HttpSession) => void | Promise<void>

Re-exported from js/net/http/server.ServerAcceptHandler.

type WebTransportReceiveStream = ReadableStream<Uint8Array> & { getStats(): Promise<WebTransportReceiveStreamStats>; }

Re-exported from js/net/http/webtransport.WebTransportReceiveStream.

type WebTransportSendStream = WritableStream<Uint8Array> & { sendGroup: string | null; sendOrder: number | null; getStats(): Promise<WebTransportSendStreamStats>; }

Re-exported from js/net/http/webtransport.WebTransportSendStream.

Interfaces

interface HttpContext {

Re-exported from app.HttpContext.

interface WebSocketContext extends HttpContext {

Re-exported from app.WebSocketContext.

interface WebTransportContext extends HttpContext {

Re-exported from app.WebTransportContext.

interface SseContext extends HttpContext {

Re-exported from app.SseContext.

interface OperationMeta {

Re-exported from app.OperationMeta.

interface OpenApiOptions {

Re-exported from app.OpenApiOptions.

interface OpenApiParameter {

Re-exported from app.OpenApiParameter.

interface OpenApiRequestBody {

Re-exported from app.OpenApiRequestBody.

interface OpenApiResponse {

Re-exported from app.OpenApiResponse.

interface Session {

Re-exported from app.Session.

interface SessionStore {

Re-exported from app.SessionStore.

interface HttpClientOptions {

Re-exported from js/net/http/client.HttpClientOptions.

interface HttpRequestInit {

Re-exported from js/net/http/client.HttpRequestInit.

interface HttpSessionRequest extends HttpRequestInit {

Re-exported from js/net/http/client.HttpSessionRequest.

interface HttpSessionOptions {

Re-exported from js/net/http/client.HttpSessionOptions.

interface ReconnectOptions {

Re-exported from js/net/http/client.ReconnectOptions.

interface CloseOptions {

Re-exported from js/net/http/client.CloseOptions.

interface HttpRequestInfo {

Re-exported from js/net/http/client.HttpRequestInfo.

interface HttpConnectionInfo {

Re-exported from js/net/http/client.HttpConnectionInfo.

interface HttpResponseTiming {

Re-exported from js/net/http/client.HttpResponseTiming.

interface SseOptions extends EventSourceInit {

Re-exported from js/net/http/client.SseOptions.

interface HttpWebSocketOptions extends WebSocketConnectOptions {

Re-exported from js/net/http/client.HttpWebSocketOptions.

interface HttpWebTransportOptions extends WebTransportOptions {

Re-exported from js/net/http/client.HttpWebTransportOptions.

interface EventSourceInit {

Re-exported from eventsource.EventSourceInit.

interface ServeOptions {

Re-exported from js/net/http/server.ServeOptions.

interface ServeServer {

Re-exported from js/net/http/server.ServeServer.

interface IncomingBase<TKind extends string> {

Re-exported from js/net/http/server.IncomingBase.

interface IncomingHttpRequest extends IncomingBase<'request'> {

Re-exported from js/net/http/server.IncomingHttpRequest.

interface AcceptedHttpRequest {

Re-exported from js/net/http/server.AcceptedHttpRequest.

interface IncomingWebSocketRequest extends IncomingBase<'websocket'> {

Re-exported from js/net/http/server.IncomingWebSocketRequest.

interface IncomingWebTransportRequest extends IncomingBase<'webtransport'> {

Re-exported from js/net/http/server.IncomingWebTransportRequest.

interface WebSocketMessage {

Re-exported from js/net/http/websocket.WebSocketMessage.

interface WebSocketAcceptOptions {

Re-exported from js/net/http/websocket.WebSocketAcceptOptions.

interface WebSocketConnectOptions {

Re-exported from js/net/http/websocket.WebSocketConnectOptions.

interface WebTransportBidirectionalStream {

Re-exported from js/net/http/webtransport.WebTransportBidirectionalStream.

interface WebTransportCloseInfo {

Re-exported from js/net/http/webtransport.WebTransportCloseInfo.

interface WebTransportHash {

Re-exported from js/net/http/webtransport.WebTransportHash.

interface WebTransportOptions {

Re-exported from js/net/http/webtransport.WebTransportOptions.

interface WebTransportReceiveStreamStats {

Re-exported from js/net/http/webtransport.WebTransportReceiveStreamStats.

interface WebTransportSendStreamStats {

Re-exported from js/net/http/webtransport.WebTransportSendStreamStats.

interface WebTransportStats {

Re-exported from js/net/http/webtransport.WebTransportStats.

Classes

abstract class BuilderBranch<TSelf extends BuilderBranch<TSelf>> {

Re-exported from app.BuilderBranch.

abstract class RouterBase<TSelf> extends BuilderBranch<RouterBranch> {

Re-exported from app.RouterBase.

class RouterBranch extends BuilderBranch<RouterBranch> {

Re-exported from app.RouterBranch.

class App extends RouterBase<App> {

Re-exported from app.App.

class Router extends RouterBase<Router> {

Re-exported from app.Router.

class RouteBuilder extends BuilderBranch<RouteBuilder> {

Re-exported from app.RouteBuilder.

class MethodBuilder extends BuilderBranch<MethodBuilder> {

Re-exported from app.MethodBuilder.

class CookieJar {

Re-exported from cookie.CookieJar.

class HttpResponse {

Re-exported from js/net/http/client.HttpResponse.

class HttpSession {

Re-exported from js/net/http/client.HttpSession.

class HttpClient {

Re-exported from js/net/http/client.HttpClient.

class EventSource extends EventTarget {

Re-exported from eventsource.EventSource.

class CloseEvent extends Event {

Re-exported from js/net/http/websocket.CloseEvent.

class ErrorEvent extends Event {

Re-exported from js/net/http/websocket.ErrorEvent.

class WebSocketError extends DOMException {

Re-exported from js/net/http/websocket.WebSocketError.

class WebSocketConnection extends EventTarget implements ConnectionTakeover {

Re-exported from js/net/http/websocket.WebSocketConnection.

class WebSocket extends EventTarget {

Re-exported from js/net/http/websocket.WebSocket.

class WebTransport {

Re-exported from js/net/http/webtransport.WebTransport.

class WebTransportDatagramDuplexStream {

Re-exported from js/net/http/webtransport.WebTransportDatagramDuplexStream.

class Arena {

Bump allocator backed by a single ArrayBuffer.

Each alloc(n) returns a Uint8Array view at the current cursor, advances the cursor by n, and never allocates a new backing store. reset() sets the cursor back to zero, logically freeing all previous allocations in O(1).

Used to eliminate per-message allocations for HTTP/1.1 request and response encoding. All bytes written into arena views are consumed by write(2) before reset() is called, so there is no aliasing hazard. If the arena is full, alloc() falls back to a regular new Uint8Array(n) — no failure mode.

The FFI layer correctly handles the non-zero byteOffset of arena views when they are passed to write(2) as buffer arguments.

const arena = new Arena(4096);
const bytes = arena.alloc(128);
arena.reset();

Constructors

constructor(size: number = 8192)

Create an arena with the requested backing-buffer size.

const arena = new Arena(65536);

Methods

alloc(n: number): Uint8Array

Allocate a Uint8Array view of n bytes.

If the arena has insufficient remaining space, this returns a standalone Uint8Array instead of throwing. Previously returned arena views are invalidated logically by reset() but not zeroed.

const header = arena.alloc(64);
reset(): void

Reset the allocation cursor to the beginning of the backing buffer.

Call this only after all views allocated from the arena have been consumed.

arena.reset();

Functions

function defineMiddleware<T extends Middleware | LayerMiddleware>( fn: T, meta: OperationMeta = { } ): T

Re-exported from app.defineMiddleware.

function defineProducer<T extends Producer>(fn: T, meta: OperationMeta = {}): T

Re-exported from app.defineProducer.

function cookies(): Producer

Re-exported from app.cookies.

function memorySessionStore(): SessionStore

Re-exported from app.memorySessionStore.

function sessions(opts: { store: SessionStore; cookie?: string; cookieOptions?: CookieOptions; }): Producer

Re-exported from app.sessions.

function errorHandler(opts: { expose?: boolean; } = {}): LayerMiddleware

Re-exported from app.errorHandler.

function staticFiles(root: string, opts: { index?: string; prefix?: string; } = {}): LayerMiddleware

Re-exported from app.staticFiles.

function serve(options: ServeOptions, handler: ServerAcceptHandler): ServeServer

Re-exported from js/net/http/server.serve.

function serveHttp(options: ServeOptions, handler: HttpRequestHandler): ServeServer

Re-exported from js/net/http/server.serveHttp.

async function parseRequest(source: AsyncIterable<Uint8Array | ArrayBuffer>): Promise<Request>

Parse an HTTP/1.x request from an async iterable of byte chunks.

The returned Request's url is constructed from the Host header and the request path: "http://<host><path>". If no Host header is present, url contains only the path.

Throws on malformed request lines, malformed headers, conflicting Content-Length, invalid chunked framing, or premature EOF.

const req = await parseRequest(reader);

async function parseResponse( source: AsyncIterable<Uint8Array | ArrayBuffer>, method?: string ): Promise<Response>

Parse an HTTP response from a byte stream.

method is the original request method; pass 'HEAD' so the parser knows the response must not expose a body even if framing headers are present. Throws on malformed status lines, headers, or body framing.

const res = await parseResponse(reader, request.method);

async function* serializeRequest(req: Request, arena?: Arena): AsyncGenerator<Uint8Array>

Serialize a Request to an async iterable of Uint8Array chunks suitable for piping to a TCP connection: request-line + headers first, then body chunks.

Body framing: - No body → no framing headers added. - content-length already present → body emitted verbatim. - Body without content-length → transfer-encoding: chunked injected.

Reading from the returned iterable consumes the request body. Passing an Arena reuses its backing buffer for generated head and chunk framing bytes.

for await (const chunk of serializeRequest(req, new Arena())) {
  await writer.write(chunk);
}

async function* serializeResponse(res: Response, arena?: Arena): AsyncGenerator<Uint8Array>

Serialize a Response to an async iterable of Uint8Array chunks suitable for piping to a TCP connection: status-line + headers first, then body chunks.

If outbound trailers are present, chunked transfer encoding is emitted and content-length is removed from the wire headers. Reading from the returned iterable consumes the response body.

for await (const chunk of serializeResponse(res, new Arena())) {
  await writer.write(chunk);
}

Constants

const schema

Re-exported from app.schema.

const body

Re-exported from app.body.