import http from 'http'; import type { Supervisor } from '../supervisor/Supervisor'; import type { RuntimeHost, RuntimeListenEndpoint } from './host/types'; export declare class GatewayProxy { private supervisor; private readonly logger; private proxy; private server; private targets; private readonly runtimeHost; private readonly listenEndpoint; private readonly exitOnStop; private readonly shutdownHandler?; private readonly baseUrl?; private readonly internalAdminAuthSecret?; private readonly clientRemoteAddressResolver?; /** * Upgrade relay for runtimes whose HTTP server cannot expose the raw upgraded * socket (Bun). `undefined` keeps the byte-level `http-proxy` relay. */ private readonly nativeUpgradeRelay?; /** Sockets created by `upgrade` events, dropped on shutdown. */ private readonly upgradeSockets; /** * Loopback-only listener used as the origin of everything that forwards remote * traffic to this Gateway (managed tunnels, P2P data plane). Requests accepted * there are never treated as local, so a forwarded request cannot inherit the * trust that a real local client has. */ private readonly ingressPort?; private ingressServer?; constructor(port: number | undefined, supervisor: Supervisor, bindHost?: string, options?: GatewayProxyOptions); /** * Builds one HTTP listener plus its WebSocket routing. * * `untrustedIngress` marks the listener that tunnels and the P2P data plane * connect to; see `ingressPort`. */ private createListener; /** * Upgraded sockets outlive the HTTP request that created them; they are * tracked so shutdown can drop them instead of waiting for a long lived * notification channel to end on its own. */ private trackUpgradeSocket; /** * Picks the internal service that owns an upgrade path. * * `/ws/*` and the device notification multiplex live on the API server; every * other upgrade (Solid notification channels, edge node tunnels) goes to CSS. */ private resolveUpgradeTarget; private relayUpgradeWithHttpProxy; setTargets(targets: { css?: string | GatewayProxyTarget; api?: string | GatewayProxyTarget; }): void; start(): Promise; stop(): Promise; /** * Closes the listener with a bounded wait. * * The listening socket stops accepting as soon as `close()` is called, but * the callback waits for every connection to end. Node keeps upgraded sockets * counted until they are destroyed (done above); Bun additionally never calls * back once a WebSocket was closed from the server side * (oven-sh/bun#28396), so waiting forever would block gateway restarts. */ private closeServer; private ingressListenEndpoint; private handleRequest; private isApiWebProductPath; private shouldRouteToApi; private pathnameFromRequestUrl; private applyInternalAdminProxyHeaders; private verifiedInternalPodProxyHeaders; private isApiHost; private configuredApiHosts; private hostsFromUrlList; private hostFromUrl; private normalizeHost; private firstHeaderValue; private stripSolidLocalRouteHeaders; private localRouteUrlFromRequest; private shouldInspectRootMutation; private shouldRejectRootResourceMutation; private writeRootMutationForbidden; private normalizeRootMutationProxyResponse; private createRootMutationForbiddenBody; private sanitizeProxyResponseHeaders; private normalizeProxiedCorsHeaders; private handleCorsPreflightRequest; /** * Add CORS headers matching CSS CorsHandler configuration */ private addCorsHeaders; private handleInternalApi; private isCssReady; private normalizeTarget; private toProxyTarget; } export interface GatewayProxyTarget { url?: string; socketPath?: string; } export interface GatewayProxyOptions { socketPath?: string; listenEndpoint?: RuntimeListenEndpoint; runtimeHost?: RuntimeHost; exitOnStop?: boolean; shutdownHandler?: () => Promise; baseUrl?: string; internalAdminAuthSecret?: string; clientRemoteAddressResolver?: (req: http.IncomingMessage) => string | undefined; /** * Forces the native (message level) upgrade relay on or off. * Defaults to `true` on Bun, where the `http-proxy` relay cannot reach the * client socket at all. */ nativeUpgradeRelay?: boolean; /** * Port for the loopback-only ingress listener that remote forwarding paths * (managed tunnels, P2P data plane) use as their origin. Omit it when the * Gateway has no remote ingress. */ ingressPort?: number; }