@stacksjs/rpx
Version:
A modern and smart reverse proxy.
71 lines (70 loc) • 3.53 kB
TypeScript
import type { PathRewrite } from './types';
import type { ResolvedAuth } from './auth';
import type { ResolvedRedirect } from './redirect';
import type { ResolvedStaticRoute } from './static-files';
import type { UpstreamPool } from './load-balancer';
/**
* Cap on client→upstream frames buffered *before the upstream WebSocket opens*.
* Without it, a fast client (or an upstream that never opens) grows `pending`
* without bound until the gateway OOMs. Beyond the cap the client socket is
* closed with 1009 (message too big). Override with `RPX_MAX_WS_PENDING_BYTES`;
* read once per handler so tests (and reloads) can pick up a new value.
*/
export declare function wsPendingCapBytes(): number;
/**
* Strip the route's mount prefix (`basePath`) from a request pathname so a
* target mounted under `/docs` sees `/` for `/docs` and `/guide` for
* `/docs/guide`. A `/` (or empty) base strips nothing. The result always keeps
* a leading `/`.
*/
export declare function stripBasePath(pathname: string, basePath?: string): string;
/**
* Build a Bun.serve-compatible `fetch` handler that routes requests based on
* the `Host` header. Returns 404 when no route matches and 502 on upstream
* failures. When a request is a WebSocket upgrade and `server` is supplied, it
* is upgraded (returns `undefined` so Bun completes the handshake) and the
* traffic is handled by the `websocket` handler from {@link createProxyWebSocketHandler}.
*/
export declare function createProxyFetchHandler(getRoute: GetRoute, verbose?: boolean, onNoRoute?: OnNoRoute): ProxyFetchHandler;
/**
* Build the `websocket` handler block for Bun.serve. It opens an upstream
* `WebSocket` per client socket, buffers client→upstream frames until the
* upstream connection is open, and pipes messages, closes and errors in both
* directions with a clean teardown.
*/
export declare function createProxyWebSocketHandler(verbose?: boolean): void;
export declare interface ProxyRoute {
sourceHost?: string
upstreamPool?: UpstreamPool
cleanUrls?: boolean
changeOrigin?: boolean
pathRewrites?: PathRewrite[]
static?: ResolvedStaticRoute
redirect?: ResolvedRedirect
basePath?: string
stripBasePathPrefix?: boolean
auth?: ResolvedAuth
}
/** Minimal shape of the Bun server needed for WebSocket upgrades. */
export declare interface ProxyServer {
upgrade: (req: Request, options?: { data?: unknown, headers?: Bun.HeadersInit }) => boolean
}
/*` → app, `/docs*` → static dir). Callers
* that only route by host can ignore the second argument — it's optional so
* existing host-only `getRoute` callbacks remain valid.
*/
export type GetRoute = (hostname: string, pathname: string) => ProxyRoute | undefined;
/**
* Outcome of the no-route fallback ({@link OnNoRoute}):
* - a `Response` — serve it as-is (e.g. a "starting…" splash);
* - `{ retry: true }` — a route was just published, so re-resolve and proxy;
* - `undefined` — no fallback applies, fall through to 404.
*/
export type NoRouteOutcome = Response | { retry: true } | undefined;
/**
* Called when `getRoute` finds nothing for a request. Lets the daemon lazily
* boot an on-demand site (see {@link import('./site-supervisor').SiteSupervisor})
* and either hold the request behind a splash or signal that the route is now live.
*/
export type OnNoRoute = (hostname: string, pathname: string, req: Request) => Promise<NoRouteOutcome>;
export type ProxyFetchHandler = (req: Request, server?: ProxyServer) => Promise<Response | undefined>;