@nestjs/core
Version:
Nest - modern, fast, powerful node.js web framework (@core)
502 lines (501 loc) • 20.1 kB
TypeScript
import type { CookieSerializeOptions, HttpServer, RequestMethod, VersioningOptions } from '@nestjs/common';
import type { RequestHandler, RouteInfo, SecurityRequestHook, VersionValue } from '@nestjs/common/internal';
import type { NestApplicationOptions } from '@nestjs/common';
import type { CookieSigner } from '../helpers/cookies/cookie-signer.js';
/**
* Base class for HTTP platform adapters (see `ExpressAdapter` and
* `FastifyAdapter` for reference implementations).
*
* It implements the {@link HttpServer} contract that the Nest core relies on,
* and that interface is where each method's calling conventions are
* documented: when the core invokes it, with which arguments, and what it
* expects back. This class only adds:
*
* - default implementations that delegate to the wrapped framework
* `instance` (`use()`, the HTTP-verb methods, `listen()`) or are inert
* (`init()`, `normalizePath()`, `mapException()`, `beforeClose()`, the
* `setOn*Hook()` setters), plus an Express-style, `use()`-based
* `registerSecurityHook()`;
* - storage for the native server (`httpServer`) and the framework instance
* (`instance`), with their accessors;
* - `setCookie()` and `clearCookie()`, implemented once on top of
* `appendHeader()`, so they behave the same on every platform;
* - the introspection hooks used by instrumentation tooling.
*
* Every remaining {@link HttpServer} member is declared abstract here, even
* the ones the interface marks optional, so subclasses cannot forget them.
* `setBaseViewsDir()`, `useBodyParser()` and `isRouteOrderSensitive()` are
* not declared on this class; implement them when the platform supports
* them (see {@link HttpServer} for what the core does when they are absent).
*
* Keep in mind that the core also reads and writes properties of the request
* object (`body`, `params`, `query`, `headers`, ...), that Server-Sent Events
* write directly to the Node.js response, and that `app.listen()` and the
* WebSocket adapters use the value returned by
* {@link AbstractHttpAdapter.getHttpServer} as a Node.js `net.Server`; see the
* {@link HttpServer} documentation for details.
*
* @typeParam TServer - Type of the native HTTP server stored in `httpServer`
* (e.g. `http.Server | https.Server`).
* @typeParam TRequest - Type of the framework request object.
* @typeParam TResponse - Type of the framework response object.
*
* @see [HTTP adapter](https://docs.nestjs.com/faq/http-adapter)
*
* @publicApi
*/
export declare abstract class AbstractHttpAdapter<TServer = any, TRequest = any, TResponse = any> implements HttpServer<TRequest, TResponse> {
protected instance?: any | undefined;
/**
* Native HTTP server created by {@link AbstractHttpAdapter.initHttpServer}
* and returned by {@link AbstractHttpAdapter.getHttpServer}.
*/
protected httpServer: TServer;
/**
* Callback registered through
* {@link AbstractHttpAdapter.setOnRouteTriggered}, if any.
*/
protected onRouteTriggered: ((requestMethod: RequestMethod, path: string) => void) | undefined;
/**
* Signer built from the `cookies.secret` application option, used by
* {@link AbstractHttpAdapter.setCookie} for `signed` cookies.
*/
protected cookieSigner: CookieSigner | undefined;
/**
* @param instance The framework application instance to delegate to (e.g.
* an Express `Application`). Subclasses typically create a default one
* when none is given.
*/
constructor(instance?: any | undefined);
/**
* Asynchronous setup hook, awaited by `NestFactory.create()` and again by
* `app.init()`, so overrides must be idempotent. No-op by default.
*
* @see {@link HttpServer.init}
*/
init(): Promise<void>;
/**
* Registers a global middleware by delegating to `instance.use(...args)`.
*
* @see {@link HttpServer.use}
*/
use(...args: any[]): any;
/**
* Registers a `GET` route by delegating to `instance.get(...args)`.
*
* @see {@link HttpServer.get}
*/
get(handler: RequestHandler): any;
get(path: any, handler: RequestHandler): any;
/**
* Registers a `POST` route by delegating to `instance.post(...args)`.
*
* @see {@link HttpServer.post}
*/
post(handler: RequestHandler): any;
post(path: any, handler: RequestHandler): any;
/**
* Registers a `HEAD` route by delegating to `instance.head(...args)`.
*
* @see {@link HttpServer.head}
*/
head(handler: RequestHandler): any;
head(path: any, handler: RequestHandler): any;
/**
* Registers a `DELETE` route by delegating to `instance.delete(...args)`.
*
* @see {@link HttpServer.delete}
*/
delete(handler: RequestHandler): any;
delete(path: any, handler: RequestHandler): any;
/**
* Registers a `PUT` route by delegating to `instance.put(...args)`.
*
* @see {@link HttpServer.put}
*/
put(handler: RequestHandler): any;
put(path: any, handler: RequestHandler): any;
/**
* Registers a `PATCH` route by delegating to `instance.patch(...args)`.
*
* @see {@link HttpServer.patch}
*/
patch(handler: RequestHandler): any;
patch(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `PROPFIND` route by delegating to
* `instance.propfind(...args)`. Override when the framework exposes the
* verb under a different API.
*
* @see {@link HttpServer.propfind}
*/
propfind(handler: RequestHandler): any;
propfind(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `PROPPATCH` route by delegating to
* `instance.proppatch(...args)`. Override when the framework exposes the
* verb under a different API.
*
* @see {@link HttpServer.proppatch}
*/
proppatch(handler: RequestHandler): any;
proppatch(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `MKCOL` route by delegating to
* `instance.mkcol(...args)`. Override when the framework exposes the verb
* under a different API.
*
* @see {@link HttpServer.mkcol}
*/
mkcol(handler: RequestHandler): any;
mkcol(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `COPY` route by delegating to
* `instance.copy(...args)`. Override when the framework exposes the verb
* under a different API.
*
* @see {@link HttpServer.copy}
*/
copy(handler: RequestHandler): any;
copy(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `MOVE` route by delegating to
* `instance.move(...args)`. Override when the framework exposes the verb
* under a different API.
*
* @see {@link HttpServer.move}
*/
move(handler: RequestHandler): any;
move(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `LOCK` route by delegating to
* `instance.lock(...args)`. Override when the framework exposes the verb
* under a different API.
*
* @see {@link HttpServer.lock}
*/
lock(handler: RequestHandler): any;
lock(path: any, handler: RequestHandler): any;
/**
* Registers a WebDAV `UNLOCK` route by delegating to
* `instance.unlock(...args)`. Override when the framework exposes the verb
* under a different API.
*
* @see {@link HttpServer.unlock}
*/
unlock(handler: RequestHandler): any;
unlock(path: any, handler: RequestHandler): any;
/**
* Registers a route for every HTTP method by delegating to
* `instance.all(...args)`.
*
* @see {@link HttpServer.all}
*/
all(handler: RequestHandler): any;
all(path: any, handler: RequestHandler): any;
/**
* Registers a `SEARCH` route by delegating to `instance.search(...args)`.
* Override when the framework exposes the verb under a different API.
*
* @see {@link HttpServer.search}
*/
search(handler: RequestHandler): any;
search(path: any, handler: RequestHandler): any;
/**
* Registers a `QUERY` route by delegating to `instance.query(...args)`.
* Override when the framework exposes the verb under a different API.
*
* @see {@link HttpServer.query}
*/
query(handler: RequestHandler): any;
query(path: any, handler: RequestHandler): any;
/**
* Registers an `OPTIONS` route by delegating to
* `instance.options(...args)`.
*
* @see {@link HttpServer.options}
*/
options(handler: RequestHandler): any;
options(path: any, handler: RequestHandler): any;
/**
* Starts listening by delegating to
* `instance.listen(port, hostname, callback)`. The core always passes its
* own callback as the last argument and expects it to be invoked once the
* server is bound, or with an `Error` on failure. Override when the
* framework instance does not expose a Node-style `listen()`, e.g. to call
* `httpServer.listen()` instead.
*
* @see {@link HttpServer.listen}
*/
listen(port: string | number, callback?: () => void): any;
listen(port: string | number, hostname: string, callback?: () => void): any;
/**
* Returns the native HTTP server stored by
* {@link AbstractHttpAdapter.initHttpServer} (or
* {@link AbstractHttpAdapter.setHttpServer}).
*
* @see {@link HttpServer.getHttpServer}
*/
getHttpServer(): TServer;
/**
* Replaces the native HTTP server returned by
* {@link AbstractHttpAdapter.getHttpServer}. Mostly useful for tests and
* for adapters that obtain the server from elsewhere.
*/
setHttpServer(httpServer: TServer): void;
/**
* Replaces the framework application instance that the default method
* implementations delegate to.
*/
setInstance<T = any>(instance: T): void;
/**
* Returns the framework application instance passed to the constructor
* (or set through {@link AbstractHttpAdapter.setInstance}).
*
* @see {@link HttpServer.getInstance}
*/
getInstance<T = any>(): T;
/**
* Converts and validates a route path before registration. Returns the
* path unchanged by default; override to translate Nest's path syntax to
* the router's and to throw on invalid paths.
*
* @see {@link HttpServer.normalizePath}
*/
normalizePath(path: string): string;
/**
* Registers a callback that the router invokes right before each route
* handler runs, with the resolved `RequestMethod` and the route path as
* declared (before {@link AbstractHttpAdapter.normalizePath}). The router
* wraps every handler at registration time, so the callback must be set
* before `app.init()` to take effect. Intended for instrumentation and
* devtools; there is no need to override it.
*/
setOnRouteTriggered(onRouteTriggered: (requestMethod: RequestMethod, path: string) => void): void;
/**
* Returns the callback registered through
* {@link AbstractHttpAdapter.setOnRouteTriggered}, if any. Read by the
* router when registering routes.
*/
getOnRouteTriggered(): ((requestMethod: RequestMethod, path: string) => void) | undefined;
/**
* Registers a hook to run at the start of every request. No-op by default;
* the built-in adapters accept a `(req, res, done) => void | Promise<void>`
* function and call `done()` to continue processing. Intended for
* instrumentation and devtools.
*/
setOnRequestHook(onRequestHook: Function): void;
/**
* Registers a hook to run once a response has been sent. No-op by default;
* the built-in adapters accept a `(req, res) => void | Promise<void>`
* function. Intended for instrumentation and devtools.
*/
setOnResponseHook(onResponseHook: Function): void;
/**
* Called by `app.close()` before the shutdown hooks run. No-op by default;
* override to enter a "shutting down" state.
*
* @see {@link HttpServer.beforeClose}
*/
beforeClose(): void;
/**
* Translates a framework-native error into something the exception filters
* understand. Invoked by the global exception layer with every error it
* receives, before it reaches the filters; the returned value is what the
* filters see. Returns the error unchanged by default. The built-in
* adapters map, for instance, body-parser `SyntaxError`s to
* `BadRequestException`.
*/
mapException(error: unknown): unknown;
/**
* Installs the request hook of the built-in HTTP security features as a
* global middleware (`use()`), which fits Express-like frameworks: the hook
* gets the request and the response, and a rejection is handed to
* `next(error)`, i.e. to the exception layer. Override when the framework
* offers an earlier request hook (the Fastify adapter uses `onRequest`).
*
* @see {@link HttpServer.registerSecurityHook}
*/
registerSecurityHook(hook: SecurityRequestHook<TRequest>): any;
/**
* Appends a `Set-Cookie` header through {@link AbstractHttpAdapter.appendHeader},
* so every cookie set during a request is sent, on every platform. The
* value is percent-encoded, `path` defaults to `/` and `maxAge` is in
* seconds (not milliseconds, unlike Express' `res.cookie()`); with
* `signed: true`, the value is signed with the first `cookies.secret`.
*
* Throws a `TypeError` when the name, the value or an attribute is not
* valid per RFC 6265 (which rules out header injection through `;`, CR or
* LF) or when `sameSite: 'none'` or `partitioned` is set without `secure`,
* and an `Error` when `signed` is set but no secret is configured.
*
* @see {@link HttpServer.setCookie}
*/
setCookie(response: TResponse, name: string, value: string, options?: CookieSerializeOptions): any;
/**
* Appends a `Set-Cookie` header that expires the cookie immediately.
* `path` and `domain` must match the ones the cookie was set with; `maxAge`,
* `expires` and `signed` are ignored.
*
* @see {@link HttpServer.clearCookie}
*/
clearCookie(response: TResponse, name: string, options?: CookieSerializeOptions): any;
/**
* Sets the signer used for `signed` cookies. Called by `NestApplication`
* with the signer it builds from the `cookies.secret` application option;
* configure that option instead of calling this method.
*
* @internal
*/
setCookieSigner(signer: CookieSigner | undefined): void;
/**
* Stops the server; called by `app.close()`. May return a promise.
*
* @see {@link HttpServer.close}
*/
abstract close(): any;
/**
* Creates the native server and stores it in `httpServer`, honoring the
* `httpsOptions`, `forceCloseConnections` and `return503OnClosing`
* application options. Called once when the application is constructed.
*
* @see {@link HttpServer.initHttpServer}
*/
abstract initHttpServer(options: NestApplicationOptions): any;
/**
* Serves static files; pass-through for `app.useStaticAssets()`.
*
* @see {@link HttpServer.useStaticAssets}
*/
abstract useStaticAssets(...args: any[]): any;
/**
* Configures the template engine used by
* {@link AbstractHttpAdapter.render}; pass-through for
* `app.setViewEngine()`.
*
* @see {@link HttpServer.setViewEngine}
*/
abstract setViewEngine(engine: string): any;
/**
* Returns the request host name, used for `@Controller({ host })`.
*
* @see {@link HttpServer.getRequestHostname}
*/
abstract getRequestHostname(request: any): any;
/**
* Returns the upper-case request method (`'GET'`, `'POST'`, ...).
*
* @see {@link HttpServer.getRequestMethod}
*/
abstract getRequestMethod(request: any): any;
/**
* Returns the original request URL, including the query string.
*
* @see {@link HttpServer.getRequestUrl}
*/
abstract getRequestUrl(request: any): any;
/**
* Sets the status code without sending the response.
*
* @see {@link HttpServer.status}
*/
abstract status(response: any, statusCode: number): any;
/**
* Sends the response body, handling empty bodies, `StreamableFile`,
* objects (as JSON) and primitives.
*
* @see {@link HttpServer.reply}
*/
abstract reply(response: any, body: any, statusCode?: number): any;
/**
* Terminates the response, optionally writing `message` first.
*
* @see {@link HttpServer.end}
*/
abstract end(response: any, message?: string): any;
/**
* Renders a view template (`@Render()`).
*
* @see {@link HttpServer.render}
*/
abstract render(response: any, view: string, options: any): any;
/**
* Issues a redirect (`@Redirect()`).
*
* @see {@link HttpServer.redirect}
*/
abstract redirect(response: any, statusCode: number, url: string): any;
/**
* Installs the global exception layer.
*
* @see {@link HttpServer.setErrorHandler}
*/
abstract setErrorHandler(handler: Function, prefix?: string): any;
/**
* Installs the catch-all handler for unmatched requests.
*
* @see {@link HttpServer.setNotFoundHandler}
*/
abstract setNotFoundHandler(handler: Function, prefix?: string, excludedRoutes?: RouteInfo[]): any;
/**
* Reports whether response headers have already been flushed. Must return
* synchronously.
*
* @see {@link HttpServer.isHeadersSent}
*/
abstract isHeadersSent(response: any): any;
/**
* Reads a response header that was set earlier. Not used by the core
* router; part of the base class so ecosystem packages can read headers
* through the adapter regardless of the platform.
*/
abstract getHeader(response: any, name: string): any;
/**
* Sets (replaces) a response header (`@Header()`).
*
* @see {@link HttpServer.setHeader}
*/
abstract setHeader(response: any, name: string, value: string): any;
/**
* Appends a value to a response header, turning it into a multi-value
* header (e.g. several `Set-Cookie` entries) instead of replacing it. Not
* used by the core router; part of the base class so ecosystem packages
* can append headers through the adapter regardless of the platform.
*/
abstract appendHeader(response: any, name: string, value: string): any;
/**
* Registers the default JSON and URL-encoded body parsers, exposing
* `req.rawBody` when `rawBody` is `true`.
*
* @see {@link HttpServer.registerParserMiddleware}
*/
abstract registerParserMiddleware(prefix?: string, rawBody?: boolean): any;
/**
* Enables CORS. The core currently calls this with `options` only; the
* `prefix` parameter is reserved.
*
* @see {@link HttpServer.enableCors}
*/
abstract enableCors(options?: any, prefix?: string): any;
/**
* Returns the function used to mount Nest middleware for one HTTP method.
* May be asynchronous.
*
* @see {@link HttpServer.createMiddlewareFactory}
*/
abstract createMiddlewareFactory(requestMethod: RequestMethod): ((path: string, callback: Function) => any) | Promise<(path: string, callback: Function) => any>;
/**
* Returns the platform identifier (`'express'`, `'fastify'`) that
* ecosystem packages branch on.
*
* @see {@link HttpServer.getType}
*/
abstract getType(): string;
/**
* Guards a route handler by request version for header, media-type and
* custom versioning.
*
* @see {@link HttpServer.applyVersionFilter}
*/
abstract applyVersionFilter(handler: Function, version: VersionValue, versioningOptions: VersioningOptions): (req: TRequest, res: TResponse, next: () => void) => Function;
}