UNPKG

@wooksjs/event-http

Version:
769 lines (747 loc) 32.9 kB
import * as _wooksjs_event_core from '@wooksjs/event-core'; import { EventContext, Logger, EventContextOptions, EventKindSeeds } from '@wooksjs/event-core'; export { EventContext, EventContextOptions, useLogger, useRouteParams } from '@wooksjs/event-core'; import * as http from 'http'; import http__default, { IncomingHttpHeaders, IncomingMessage, ServerResponse, Server } from 'http'; import { Buffer } from 'buffer'; import { URLSearchParams } from 'url'; import * as wooks from 'wooks'; import { TWooksHandler, TWooksOptions, WooksAdapterBase, Wooks, WooksUpgradeHandler } from 'wooks'; import { TConsoleBase } from '@prostojs/logger'; import { ListenOptions } from 'net'; import { Duplex } from 'stream'; /** * Provides access to parsed request cookies. * @example * ```ts * const { getCookie, raw } = useCookies() * const sessionId = getCookie('session_id') * ``` */ declare const useCookies: _wooksjs_event_core.WookComposable<{ raw: string | undefined; getCookie: (name: string) => string | null; }>; /** Short names for common Accept MIME types. */ type KnownAcceptType = 'json' | 'html' | 'xml' | 'text'; /** Provides helpers to check the request's Accept header for supported MIME types. */ declare const useAccept: _wooksjs_event_core.WookComposable<{ accept: string | undefined; has: (type: KnownAcceptType | (string & {})) => boolean; }>; /** Short names for common Authorization schemes. */ type KnownAuthType = 'basic' | 'bearer'; /** * Provides parsed access to the Authorization header (type, credentials, Basic decoding). * @example * ```ts * const { is, credentials, basicCredentials } = useAuthorization() * if (is('bearer')) { const token = credentials() } * ``` */ declare const useAuthorization: _wooksjs_event_core.WookComposable<{ authorization: string | undefined; type: () => string | null; credentials: () => string | null; is: (type: KnownAuthType | (string & {})) => boolean; basicCredentials: () => { username: string; password: string; } | null; }>; /** * Returns the incoming request headers. * @example * ```ts * const { host, authorization } = useHeaders() * ``` */ declare function useHeaders(ctx?: EventContext): IncomingHttpHeaders; /** Default safety limits for request body reading (size, ratio, timeout). */ declare const DEFAULT_LIMITS: { readonly maxCompressed: number; readonly maxInflated: number; readonly maxRatio: 100; readonly readTimeoutMs: 10000; }; /** @internal Exported for test pre-seeding via `ctx.set(rawBodySlot, ...)`. */ declare const rawBodySlot: _wooksjs_event_core.Cached<Promise<Buffer<ArrayBufferLike>>>; /** * Provides access to the incoming HTTP request (method, url, headers, body, IP). * @example * ```ts * const { method, url, raw, rawBody, getIp } = useRequest() * const body = await rawBody() * ``` */ declare const useRequest: _wooksjs_event_core.WookComposable<{ raw: http.IncomingMessage; url: string | undefined; method: string | undefined; headers: http.IncomingHttpHeaders; rawBody: () => Promise<Buffer<ArrayBufferLike>>; reqId: () => string; getIp: (options?: { trustProxy: boolean; }) => string; getIpList: () => { remoteIp: string; forwarded: string[]; }; isCompressed: () => boolean; getMaxCompressed: () => number; setMaxCompressed: (limit: number) => void; getReadTimeoutMs: () => number; setReadTimeoutMs: (limit: number) => void; getMaxInflated: () => number; setMaxInflated: (limit: number) => void; getMaxRatio: () => number; setMaxRatio: (limit: number) => void; }>; /** Maps numeric HTTP status codes to their human-readable descriptions. */ declare const httpStatusCodes: { 100: string; 101: string; 102: string; 103: string; 200: string; 201: string; 202: string; 203: string; 204: string; 205: string; 206: string; 207: string; 208: string; 226: string; 300: string; 301: string; 302: string; 303: string; 304: string; 305: string; 306: string; 307: string; 308: string; 400: string; 401: string; 402: string; 403: string; 404: string; 405: string; 406: string; 407: string; 408: string; 409: string; 410: string; 411: string; 412: string; 413: string; 414: string; 415: string; 416: string; 417: string; 418: string; 421: string; 422: string; 423: string; 424: string; 425: string; 426: string; 428: string; 429: string; 431: string; 451: string; 500: string; 501: string; 502: string; 503: string; 504: string; 505: string; 506: string; 507: string; 508: string; 510: string; 511: string; }; /** Enum of all standard HTTP status codes (100–511). */ declare enum EHttpStatusCode { Continue = 100, SwitchingProtocols = 101, Processing = 102, EarlyHints = 103, OK = 200, Created = 201, Accepted = 202, NonAuthoritativeInformation = 203, NoContent = 204, ResetContent = 205, PartialContent = 206, MultiStatus = 207, AlreadyReported = 208, IMUsed = 226, MultipleChoices = 300, MovedPermanently = 301, Found = 302, SeeOther = 303, NotModified = 304, UseProxy = 305, SwitchProxy = 306, TemporaryRedirect = 307, PermanentRedirect = 308, BadRequest = 400, Unauthorized = 401, PaymentRequired = 402, Forbidden = 403, NotFound = 404, MethodNotAllowed = 405, NotAcceptable = 406, ProxyAuthenticationRequired = 407, RequestTimeout = 408, Conflict = 409, Gone = 410, LengthRequired = 411, PreconditionFailed = 412, PayloadTooLarge = 413, URITooLong = 414, UnsupportedMediaType = 415, RangeNotSatisfiable = 416, ExpectationFailed = 417, ImATeapot = 418, MisdirectedRequest = 421, UnprocessableEntity = 422, Locked = 423, FailedDependency = 424, TooEarly = 425, UpgradeRequired = 426, PreconditionRequired = 428, TooManyRequests = 429, RequestHeaderFieldsTooLarge = 431, UnavailableForLegalReasons = 451, InternalServerError = 500, NotImplemented = 501, BadGateway = 502, ServiceUnavailable = 503, GatewayTimeout = 504, HTTPVersionNotSupported = 505, VariantAlsoNegotiates = 506, InsufficientStorage = 507, LoopDetected = 508, NotExtended = 510, NetworkAuthenticationRequired = 511 } /** Union of HTTP 4xx client error status codes. */ type THttpBadRequestCodes = 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 421 | 422 | 423 | 424 | 425 | 426 | 428 | 429 | 431 | 451; /** Union of HTTP 5xx server error status codes. */ type THttpServerErrorCodes = 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 510 | 511; /** Union of all HTTP error status codes (4xx + 5xx). */ type THttpErrorCodes = THttpBadRequestCodes | THttpServerErrorCodes; /** Represents an HTTP error with a status code and optional structured body. */ declare class HttpError<T extends TWooksErrorBody = TWooksErrorBody> extends Error { protected code: THttpErrorCodes; protected _body: string | T; name: string; constructor(code?: THttpErrorCodes, _body?: string | T); get body(): TWooksErrorBodyExt; } /** Base shape for an HTTP error response body. */ interface TWooksErrorBody { message: string; statusCode: EHttpStatusCode; error?: string; } /** Extended error body that always includes the error description string. */ interface TWooksErrorBodyExt extends TWooksErrorBody { error: string; } type TTimeUnit = 'ms' | 's' | 'm' | 'h' | 'd' | 'w' | 'M' | 'Y'; type TTimeSingleString = `${number}${TTimeUnit}`; type TTimeMultiString = `${TTimeSingleString}${TTimeSingleString | ''}${TTimeSingleString | ''}${TTimeSingleString | ''}`; /** Raw HTTP event data attached to the event context. */ interface THttpEventData { req: IncomingMessage; res: ServerResponse; requestLimits?: TRequestLimits; } /** Data for a pending outgoing `Set-Cookie` header (name is stored as the key in `HttpResponse._cookies`). */ interface TSetCookieData { value: string; attrs: TCookieAttributesInput; } /** Partial cookie attributes — all fields are optional. */ type TCookieAttributesInput = Partial<TCookieAttributes>; /** Full set of attributes for a `Set-Cookie` header (RFC 6265 §4.1). */ interface TCookieAttributes { /** Cookie expiration date. */ expires: Date | string | number; /** Max age in seconds, or a time string (e.g. `'1h'`). */ maxAge: number | TTimeMultiString; /** Cookie domain. */ domain: string; /** Cookie path. */ path: string; /** Secure flag — cookie only sent over HTTPS. */ secure: boolean; /** HttpOnly flag — cookie not accessible via JavaScript. */ httpOnly: boolean; /** SameSite policy. */ sameSite: boolean | 'Lax' | 'None' | 'Strict'; } /** App-level request body limits (all optional, defaults apply when omitted). */ interface TRequestLimits { /** Max compressed body size in bytes (default: 1 MB). */ maxCompressed?: number; /** Max inflated (decompressed) body size in bytes (default: 10 MB). */ maxInflated?: number; /** Max compression ratio, e.g. 100 means 100× expansion (default: 100). */ maxRatio?: number; /** Body read timeout in milliseconds (default: 10 000). */ readTimeoutMs?: number; /** Internal flag: true when this object is a per-request clone (copy-on-write). */ perRequest?: boolean; } /** Cache-Control directive object (RFC 7234 §5.2.2). All fields are optional. */ interface TCacheControl { mustRevalidate?: boolean; noCache?: boolean | string; noStore?: boolean; noTransform?: boolean; public?: boolean; private?: boolean | string; proxyRevalidate?: boolean; /** Max age in seconds, or a time string (e.g. `'3h 30m'`). */ maxAge?: number | TTimeMultiString; /** Shared cache max age in seconds, or a time string. */ sMaxage?: number | TTimeMultiString; } /** Renders a `TCacheControl` object into a `Cache-Control` header string. */ declare function renderCacheControl(data: TCacheControl): string; /** * Manages response status, headers, cookies, cache control, and body for an HTTP request. * * All header mutations are accumulated in memory and flushed in a single `writeHead()` call * when `send()` is invoked. Setter methods are chainable. * * @example * ```ts * const response = useResponse() * response.setStatus(200).setHeader('x-custom', 'value') * response.setCookie('session', 'abc', { httpOnly: true }) * ``` */ declare class HttpResponse { protected readonly _res: ServerResponse; protected readonly _req: IncomingMessage; protected readonly _logger: Logger; protected readonly _captureMode: boolean; /** * @param _res - The underlying Node.js `ServerResponse`. * @param _req - The underlying Node.js `IncomingMessage`. * @param _logger - Logger instance for error reporting. * @param defaultHeaders - Optional headers to pre-populate on this response (e.g. from `securityHeaders()`). */ constructor(_res: ServerResponse, _req: IncomingMessage, _logger: Logger, defaultHeaders?: Record<string, string | string[]>, _captureMode?: boolean); protected _status: EHttpStatusCode; protected _body: unknown; protected _headers: Record<string, string | string[]>; protected _cookies: Record<string, TSetCookieData>; protected _rawCookies: string[]; protected _hasCookies: boolean; protected _responded: boolean; /** The HTTP status code. If not set, it is inferred automatically when `send()` is called. */ get status(): EHttpStatusCode; set status(value: EHttpStatusCode); /** Sets the HTTP status code (chainable). */ setStatus(value: EHttpStatusCode): this; /** The response body. Automatically serialized by `send()` (objects → JSON, strings → text). */ get body(): unknown; set body(value: unknown); /** Sets the response body (chainable). */ setBody(value: unknown): this; /** Sets a single response header (chainable). Arrays produce multi-value headers. */ setHeader(name: string, value: string | number | string[]): this; /** Batch-sets multiple response headers from a record (chainable). Existing keys are overwritten. */ setHeaders(headers: Record<string, string | string[]>): this; /** Returns the value of a response header, or `undefined` if not set. */ getHeader(name: string): string | string[] | undefined; /** Removes a response header (chainable). */ removeHeader(name: string): this; /** Returns a read-only snapshot of all response headers. */ headers(): Readonly<Record<string, string | string[]>>; /** Sets the `Content-Type` response header (chainable). */ setContentType(value: string): this; /** Returns the current `Content-Type` header value. */ getContentType(): string | string[] | undefined; /** Sets the `Access-Control-Allow-Origin` header (chainable). Defaults to `'*'`. */ enableCors(origin?: string): this; /** Sets an outgoing `Set-Cookie` header with optional attributes (chainable). */ setCookie(name: string, value: string, attrs?: Partial<TCookieAttributes>): this; /** Returns a previously set cookie's data, or `undefined` if not set. */ getCookie(name: string): TSetCookieData | undefined; /** Removes a cookie from the outgoing set list (chainable). */ removeCookie(name: string): this; /** Removes all outgoing cookies (chainable). */ clearCookies(): this; /** Appends a raw `Set-Cookie` header string (chainable). Use when you need full control over the cookie format. */ setCookieRaw(rawValue: string): this; /** * Renders all buffered cookies (named via `setCookie()`, then raw via `setCookieRaw()`) * as `Set-Cookie` header strings, without responding. * * Non-destructive: the buffers stay intact, so a later `send()` still emits the same * cookies — callers that drain cookies onto the wire themselves should not also send * through this wrapper. Cookies placed directly into headers (via `setHeader('set-cookie', …)` * or default headers) are not included. */ getSetCookieStrings(): string[]; /** Sets the `Cache-Control` header from a directive object (chainable). */ setCacheControl(data: TCacheControl): this; /** Sets the `Age` header in seconds (chainable). Accepts a number or time string (e.g. `'2h 15m'`). */ setAge(value: number | TTimeMultiString): this; /** Sets the `Expires` header (chainable). Accepts a `Date`, date string, or timestamp. */ setExpires(value: Date | string | number): this; /** Sets or clears the `Pragma: no-cache` header (chainable). */ setPragmaNoCache(value?: boolean): this; /** * Returns the underlying Node.js `ServerResponse`. * @param passthrough - If `true`, the framework still manages the response lifecycle. If `false` (default), the response is marked as "responded" and the framework will not touch it. */ getRawRes(passthrough?: boolean): ServerResponse; /** Whether the response has already been sent (or the underlying stream is no longer writable). */ get responded(): boolean; /** * Builds a Web Standard `Response` from the accumulated response state * (status, headers, cookies, body) without writing to the underlying `ServerResponse`. * * Used by `WooksHttp.fetch()` for programmatic invocation. */ toWebResponse(): Response; private _buildWebHeaders; /** * Merges headers from a handler-returned fetch `Response` into the buffered headers. * Explicitly buffered headers win. `set-cookie` is appended in array form so multiple * cookies survive (`Headers` iteration would otherwise keep only the first). */ protected mergeFetchResponseHeaders(fetchResponse: Response): void; protected renderBody(): string | Uint8Array; protected renderError(data: TWooksErrorBodyExt, _ctx: EventContext): void; /** Renders and sends an HTTP error response. Called automatically by the framework when a handler throws an `HttpError`. */ sendError(error: HttpError, ctx: EventContext): void | Promise<void>; /** * Finalizes and sends the response. * * Flushes all accumulated headers (including cookies) in a single `writeHead()` call, * then writes the body. Supports `Readable` streams, `fetch` `Response` objects, and regular values. * * @throws Error if the response was already sent. */ send(): void | Promise<void>; private finalizeCookies; private autoStatus; private sendStream; private sendFetchResponse; private sendRegular; } /** Converts a Record of headers to a Web Standard `Headers` object. */ declare function recordToWebHeaders(record: Record<string, string | string[]>): Headers; /** * Returns the HttpResponse instance for the current request. * All response operations (status, headers, cookies, cache control, sending) * are methods on the returned object. * * @example * ```ts * const response = useResponse() * response.status = 200 * response.setHeader('x-custom', 'value') * response.setCookie('session', 'abc', { httpOnly: true }) * ``` */ declare function useResponse(ctx?: EventContext): HttpResponse; /** * Extended `URLSearchParams` with safe JSON conversion. * * Rejects prototype-pollution keys (`__proto__`, `constructor`, `prototype`) and duplicate non-array keys. * Array parameters are detected by a trailing `[]` in the key name (e.g. `tags[]=a&tags[]=b`). */ declare class WooksURLSearchParams extends URLSearchParams { /** Converts query parameters to a plain object. Array params (keys ending with `[]`) become `string[]`. */ toJson<T = unknown>(): T; } /** * Provides access to URL search (query) parameters from the request. * @example * ```ts * const { params, toJson } = useUrlParams() * const page = params().get('page') * ``` */ declare const useUrlParams: _wooksjs_event_core.WookComposable<{ raw: () => string; params: () => WooksURLSearchParams; toJson: () => unknown; }>; /** Event kind definition for HTTP requests. Provides typed context slots for `req`, `response`, and `requestLimits`. */ declare const httpKind: _wooksjs_event_core.EventKind<{ req: _wooksjs_event_core.SlotMarker<IncomingMessage>; response: _wooksjs_event_core.SlotMarker<HttpResponse | undefined>; requestLimits: _wooksjs_event_core.SlotMarker<TRequestLimits | undefined>; }>; /** Creates an HTTP event context and runs `fn` inside it. */ declare function createHttpContext<R>(options: EventContextOptions, seeds: EventKindSeeds<typeof httpKind>, fn: () => R): R; /** Returns the current HTTP event context. */ declare function useHttpContext(ctx?: EventContext): EventContext; /** * Default `HttpResponse` subclass used by `createHttpApp`. * * Overrides error rendering to produce content-negotiated responses (JSON, HTML, or plain text) * based on the request's `Accept` header. HTML error pages include SVG icons and framework branding. */ declare class WooksHttpResponse extends HttpResponse { /** Registers framework metadata (name, version, link, logo) used in HTML error pages. */ static registerFramework(opts: { version: string; poweredBy: string; link: string; image: string; }): void; protected renderError(data: TWooksErrorBodyExt, ctx: EventContext): void; } /** * Identity headers forwarded from the calling HTTP context during programmatic `fetch()` * when no `forwardHeaders` option is configured. * * The `forwardHeaders` option REPLACES this list. To extend it instead, spread the constant: * ```ts * createHttpApp({ forwardHeaders: [...DEFAULT_FORWARD_HEADERS, 'cloudfront-viewer-address'] }) * ``` */ declare const DEFAULT_FORWARD_HEADERS: readonly string[]; /** Configuration options for the WooksHttp adapter. */ interface TWooksHttpOptions { logger?: TConsoleBase; onNotFound?: TWooksHandler; router?: TWooksOptions['router']; /** Default request body limits applied to every request (overridable per-request via `useRequest()`). */ requestLimits?: Omit<TRequestLimits, 'perRequest'>; /** Custom HttpResponse subclass. Defaults to WooksHttpResponse (HTML/JSON/text error rendering). */ responseClass?: typeof WooksHttpResponse; /** Default headers applied to every response. Use `securityHeaders()` for recommended security headers. */ defaultHeaders?: Record<string, string | string[]>; /** * Headers forwarded from the calling HTTP context during programmatic `fetch()`. * REPLACES the default list entirely — to add headers while keeping the defaults, * spread the exported constant: `[...DEFAULT_FORWARD_HEADERS, 'my-header']`. * Set to `false` to disable forwarding entirely. * @default DEFAULT_FORWARD_HEADERS — ['authorization', 'cookie', 'accept-language', 'x-forwarded-for', 'x-request-id'] */ forwardHeaders?: string[] | false; } /** HTTP adapter for Wooks that provides route registration, server lifecycle, and request handling. */ declare class WooksHttp extends WooksAdapterBase { protected opts?: TWooksHttpOptions | undefined; protected logger: TConsoleBase; protected ResponseClass: typeof WooksHttpResponse; protected eventContextOptions: EventContextOptions; constructor(opts?: TWooksHttpOptions | undefined, wooks?: Wooks | WooksAdapterBase); /** Registers a handler for all HTTP methods on the given path. */ all<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers a GET route handler. */ get<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers a POST route handler. */ post<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers a PUT route handler. */ put<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers a PATCH route handler. */ patch<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers a DELETE route handler. */ delete<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers a HEAD route handler. */ head<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers an OPTIONS route handler. */ options<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; /** Registers an UPGRADE route handler for WebSocket upgrade requests. */ upgrade<ResType = unknown, ParamsType = Record<string, string | string[]>>(path: string, handler: TWooksHandler<ResType>): wooks.TProstoRouterPathHandle<ParamsType>; private wsHandler?; /** Register a WebSocket upgrade handler that implements the WooksUpgradeHandler contract. */ ws(handler: WooksUpgradeHandler): void; protected server?: Server; /** * Starts the http(s) server. * * Use this only if you rely on Wooks server. */ listen(port?: number, hostname?: string, backlog?: number, listeningListener?: () => void): Promise<void>; listen(port?: number, hostname?: string, listeningListener?: () => void): Promise<void>; listen(port?: number, backlog?: number, listeningListener?: () => void): Promise<void>; listen(port?: number, listeningListener?: () => void): Promise<void>; listen(path: string, backlog?: number, listeningListener?: () => void): Promise<void>; listen(path: string, listeningListener?: () => void): Promise<void>; listen(options: ListenOptions, listeningListener?: () => void): Promise<void>; listen(handle: unknown, backlog?: number, listeningListener?: () => void): Promise<void>; listen(handle: unknown, listeningListener?: () => void): Promise<void>; /** * Stops the server if it was attached or passed via argument * @param server */ close(server?: Server): Promise<unknown>; /** * Returns http(s) server that was attached to Wooks * * See attachServer method docs * @returns Server */ getServer(): http__default.Server<typeof http__default.IncomingMessage, typeof http__default.ServerResponse> | undefined; /** * Attaches http(s) server instance * to Wooks. * * Use it only if you want to `close` method to stop the server. * @param server Server */ attachServer(server?: Server): void; protected respond(data: unknown, response: HttpResponse, ctx: EventContext): void | Promise<void>; /** * Returns server callback function * that can be passed to any node server: * ```js * import { createHttpApp } from '@wooksjs/event-http' * import http from 'http' * * const app = createHttpApp() * const server = http.createServer(app.getServerCb()) * server.listen(3000) * ``` */ getServerCb(onNoMatch?: (req: IncomingMessage, res: ServerResponse) => void): (req: IncomingMessage, res: ServerResponse) => void; /** * Returns upgrade callback function for the HTTP server's 'upgrade' event. * Creates an HTTP context, seeds it with upgrade data, and routes as method 'UPGRADE'. */ getUpgradeCb(): (req: IncomingMessage, socket: Duplex, head: Buffer) => void; protected processUpgradeHandlers(handlers: TWooksHandler[], ctx: EventContext, socket: Duplex): void | Promise<unknown>; /** Runs handlers and attaches a `.catch()` for async results to avoid unhandled rejections. */ private processAndCatch; protected processHandlers(handlers: TWooksHandler[], ctx: EventContext, response: HttpResponse): void | Promise<unknown>; private processAsyncResult; /** * Programmatic route invocation using the Web Standard fetch API. * Goes through the full dispatch pipeline: context creation, route matching, * handler execution, response finalization. * * When called from within an existing HTTP context (e.g. during SSR), * identity headers (authorization, cookie) are automatically forwarded * from the calling request unless already present on the given Request. * * @param request - A Web Standard Request object. * @returns A Web Standard Response, or `null` if no route matched (and no `onNotFound` handler is set). */ fetch(request: Request): Promise<Response | null>; /** * Convenience wrapper for programmatic route invocation. * Accepts a URL string (relative paths auto-prefixed with `http://localhost`), * URL object, or Request, plus optional `RequestInit`. * * @param input - URL string, URL object, or Request. * @param init - Optional RequestInit (method, headers, body, etc.). * @returns A Web Standard Response. */ request(input: string | URL | Request, init?: RequestInit): Promise<Response | null>; /** * Runs `fn` inside an HTTP event context seeded from a real `(req, res)` pair, * WITHOUT route dispatch. Composables that read request state (`useRequest`, * `useHeaders`, `useCookies`, `useAuthorization`) work; route-scoped state is empty. * Nested `fetch()` calls made during `fn` see this context as their caller, * so `forwardHeaders` and parent `Set-Cookie` propagation apply. * * Never writes to `res` — the caller owns the wire. The response wrapper is * created in capture mode, so even a stray `response.send()` inside `fn` only * finalizes state without touching the socket. Buffered response state * (e.g. `Set-Cookie` collected from nested fetches) can be applied by the * caller via the returned wrapper: * ```ts * const { result: html, response } = await http.withHttpContext(req, res, () => render(url)) * for (const cookie of response.getSetCookieStrings()) { * res.appendHeader('Set-Cookie', cookie) * } * ``` */ withHttpContext<T>(req: IncomingMessage, res: ServerResponse, fn: () => T): Promise<{ result: Awaited<T>; response: HttpResponse; }>; } /** * Creates a new WooksHttp application instance. * @example * ```ts * const app = createHttpApp() * app.get('/hello', () => 'Hello World!') * app.listen(3000) * ``` */ declare function createHttpApp(opts?: TWooksHttpOptions, wooks?: Wooks | WooksAdapterBase): WooksHttp; /** * Configuration for `securityHeaders()`. Each option accepts a `string` (override value), * `false` (disable), or `undefined` (use default). `strictTransportSecurity` has no default (opt-in only). */ interface SecurityHeadersOptions { /** `Content-Security-Policy` header. Default: `"default-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'self'"`. */ contentSecurityPolicy?: string | false; /** `Cross-Origin-Opener-Policy` header. Default: `'same-origin'`. */ crossOriginOpenerPolicy?: string | false; /** `Cross-Origin-Resource-Policy` header. Default: `'same-origin'`. */ crossOriginResourcePolicy?: string | false; /** `Referrer-Policy` header. Default: `'no-referrer'`. */ referrerPolicy?: string | false; /** `Strict-Transport-Security` header. No default (opt-in only — HSTS is dangerous if not on HTTPS). */ strictTransportSecurity?: string | false; /** `X-Content-Type-Options` header. Default: `'nosniff'`. */ xContentTypeOptions?: string | false; /** `X-Frame-Options` header. Default: `'SAMEORIGIN'`. */ xFrameOptions?: string | false; } /** * Returns a record of recommended HTTP security headers. * * Each option accepts a `string` (override value) or `false` (disable). * Omitting an option uses the default value. * * `strictTransportSecurity` is opt-in only (no default) — HSTS is dangerous if not on HTTPS. */ declare function securityHeaders(opts?: SecurityHeadersOptions): Record<string, string>; /** Options for creating a test HTTP event context. */ interface TTestHttpContext { /** Pre-set route parameters (e.g. `{ id: '42' }`). */ params?: Record<string, string | string[]>; /** Request URL (e.g. `/api/users?page=1`). */ url: string; /** Request headers. */ headers?: Record<string, string>; /** HTTP method (default: `'GET'`). */ method?: string; /** Custom request body limits. */ requestLimits?: TRequestLimits; /** Pre-seed the raw body for body-parsing tests. */ rawBody?: string | Buffer; /** Default headers to pre-populate on the response (e.g. from `securityHeaders()`). */ defaultHeaders?: Record<string, string | string[]>; } /** * Creates a fully initialized HTTP event context for testing. * * Sets up an `EventContext` with a fake `IncomingMessage`, `HttpResponse`, route params, * and optional pre-seeded body. Returns a runner function that executes callbacks inside the context scope. * * @example * ```ts * const run = prepareTestHttpContext({ url: '/users/42', params: { id: '42' } }) * run(() => { * const { params } = useRouteParams() * expect(params.id).toBe('42') * }) * ``` */ declare function prepareTestHttpContext(options: TTestHttpContext): <T>(cb: (...a: any[]) => T) => T; export { DEFAULT_FORWARD_HEADERS, DEFAULT_LIMITS, EHttpStatusCode, HttpError, HttpResponse, WooksHttp, WooksHttpResponse, WooksURLSearchParams, createHttpApp, createHttpContext, httpKind, httpStatusCodes, prepareTestHttpContext, rawBodySlot, recordToWebHeaders, renderCacheControl, securityHeaders, useAccept, useAuthorization, useCookies, useHeaders, useHttpContext, useRequest, useResponse, useUrlParams }; export type { KnownAcceptType, KnownAuthType, SecurityHeadersOptions, TCacheControl, TCookieAttributes, TCookieAttributesInput, THttpEventData, TRequestLimits, TSetCookieData, TTestHttpContext, TWooksErrorBody, TWooksErrorBodyExt, TWooksHttpOptions };