UNPKG

@nestjs/core

Version:

Nest - modern, fast, powerful node.js web framework (@core)

502 lines (501 loc) • 20.1 kB
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; }