/// import { Application, Binding, BindingAddress, Constructor, Server } from '@loopback/core'; import { BaseMiddlewareRegistry, ExpressRequestHandler } from '@loopback/express'; import { HttpServer, HttpServerOptions } from '@loopback/http-server'; import { OASEnhancerService, OpenApiSpec, OperationObject, ServerObject } from '@loopback/openapi-v3'; import cors from 'cors'; import express, { ErrorRequestHandler } from 'express'; import { PathParams } from 'express-serve-static-core'; import { IncomingMessage, ServerResponse } from 'http'; import { ServeStaticOptions } from 'serve-static'; import { BodyParser } from './body-parsers'; import { HttpHandler } from './http-handler'; import { RequestContext } from './request-context'; import { ControllerClass, ControllerFactory, ControllerInstance, RestRouterOptions, RouteEntry, RouterSpec } from './router'; import { SequenceFunction, SequenceHandler } from './sequence'; import { Request, RequestBodyParserOptions, Response } from './types'; export declare type HttpRequestListener = (req: IncomingMessage, res: ServerResponse) => void; export interface HttpServerLike { requestHandler: HttpRequestListener; } /** * A REST API server for use with Loopback. * Add this server to your application by importing the RestComponent. * * @example * ```ts * const app = new MyApplication(); * app.component(RestComponent); * ``` * * To add additional instances of RestServer to your application, use the * `.server` function: * ```ts * app.server(RestServer, 'nameOfYourServer'); * ``` * * By default, one instance of RestServer will be created when the RestComponent * is bootstrapped. This instance can be retrieved with * `app.getServer(RestServer)`, or by calling `app.get('servers.RestServer')` * Note that retrieving other instances of RestServer must be done using the * server's name: * ```ts * const server = await app.getServer('foo') * // OR * const server = await app.get('servers.foo'); * ``` */ export declare class RestServer extends BaseMiddlewareRegistry implements Server, HttpServerLike { /** * Handle incoming HTTP(S) request by invoking the corresponding * Controller method via the configured Sequence. * * @example * * ```ts * const app = new Application(); * app.component(RestComponent); * // setup controllers, etc. * * const restServer = await app.getServer(RestServer); * const httpServer = http.createServer(restServer.requestHandler); * httpServer.listen(3000); * ``` * * @param req - The request. * @param res - The response. */ protected oasEnhancerService: OASEnhancerService; get OASEnhancer(): OASEnhancerService; protected _requestHandler: HttpRequestListener; get requestHandler(): HttpRequestListener; readonly config: RestServerResolvedConfig; private _basePath; protected _httpHandler: HttpHandler; protected get httpHandler(): HttpHandler; /** * Context event subscriptions for route related changes */ private _routesEventSubscription; protected _httpServer: HttpServer | undefined; protected _expressApp?: express.Application; get listening(): boolean; get httpServer(): HttpServer | undefined; /** * The base url for the server, including the basePath if set. For example, * the value will be 'http://localhost:3000/api' if `basePath` is set to * '/api'. */ get url(): string | undefined; /** * The root url for the server without the basePath. For example, the value * will be 'http://localhost:3000' regardless of the `basePath`. */ get rootUrl(): string | undefined; /** * * Creates an instance of RestServer. * * @param app - The application instance (injected via * CoreBindings.APPLICATION_INSTANCE). * @param config - The configuration options (injected via * RestBindings.CONFIG). * */ constructor(app: Application, config?: RestServerConfig); protected _setupOASEnhancerIfNeeded(): void; protected _setupRequestHandlerIfNeeded(): void; /** * Get an Express handler for unexpected errors */ protected _unexpectedErrorHandler(): ErrorRequestHandler; /** * Apply express settings. */ protected _applyExpressSettings(): void; /** * Mount /openapi.json, /openapi.yaml for specs and /swagger-ui, /explorer * to redirect to externally hosted API explorer */ protected _setupOpenApiSpecEndpoints(): void; /** * Add a new non-controller endpoint hosting a form of the OpenAPI spec. * * @param path Path at which to host the copy of the OpenAPI * @param form Form that should be rendered from that path */ addOpenApiSpecEndpoint(path: string, form: OpenApiSpecForm, router?: express.Router): void; protected _handleHttpRequest(request: Request, response: Response): Promise; protected _setupHandlerIfNeeded(): void; /** * Create an instance of HttpHandler and populates it with routes */ private _createHttpHandler; private _setupOperation; private _serveOpenApiSpec; private _redirectToSwaggerUI; /** * Register a controller class with this server. * * @param controllerCtor - The controller class * (constructor function). * @returns The newly created binding, you can use the reference to * further modify the binding, e.g. lock the value to prevent further * modifications. * * @example * ```ts * class MyController { * } * app.controller(MyController).lock(); * ``` * */ controller(controllerCtor: ControllerClass): Binding; /** * Register a new Controller-based route. * * @example * ```ts * class MyController { * greet(name: string) { * return `hello ${name}`; * } * } * app.route('get', '/greet', operationSpec, MyController, 'greet'); * ``` * * @param verb - HTTP verb of the endpoint * @param path - URL path of the endpoint * @param spec - The OpenAPI spec describing the endpoint (operation) * @param controllerCtor - Controller constructor * @param controllerFactory - A factory function to create controller instance * @param methodName - The name of the controller method */ route(verb: string, path: string, spec: OperationObject, controllerCtor: ControllerClass, controllerFactory: ControllerFactory, methodName: string): Binding; /** * Register a new route invoking a handler function. * * @example * ```ts * function greet(name: string) { * return `hello ${name}`; * } * app.route('get', '/', operationSpec, greet); * ``` * * @param verb - HTTP verb of the endpoint * @param path - URL path of the endpoint * @param spec - The OpenAPI spec describing the endpoint (operation) * @param handler - The function to invoke with the request parameters * described in the spec. */ route(verb: string, path: string, spec: OperationObject, handler: Function): Binding; /** * Register a new generic route. * * @example * ```ts * function greet(name: string) { * return `hello ${name}`; * } * const route = new Route('get', '/', operationSpec, greet); * app.route(route); * ``` * * @param route - The route to add. */ route(route: RouteEntry): Binding; private bindRoute; /** * Register a route redirecting callers to a different URL. * * @example * ```ts * server.redirect('/explorer', '/explorer/'); * ``` * * @param fromPath - URL path of the redirect endpoint * @param toPathOrUrl - Location (URL path or full URL) where to redirect to. * If your server is configured with a custom `basePath`, then the base path * is prepended to the target location. * @param statusCode - HTTP status code to respond with, * defaults to 303 (See Other). */ redirect(fromPath: string, toPathOrUrl: string, statusCode?: number): Binding; private _externalRoutes; /** * Mount static assets to the REST server. * See https://expressjs.com/en/4x/api.html#express.static * @param path - The path(s) to serve the asset. * See examples at https://expressjs.com/en/4x/api.html#path-examples * @param rootDir - The root directory from which to serve static assets * @param options - Options for serve-static */ static(path: PathParams, rootDir: string, options?: ServeStaticOptions): void; /** * Set the OpenAPI specification that defines the REST API schema for this * server. All routes, parameter definitions and return types will be defined * in this way. * * Note that this will override any routes defined via decorators at the * controller level (this function takes precedent). * * @param spec - The OpenAPI specification, as an object. * @returns Binding for the spec * */ api(spec: OpenApiSpec): Binding; /** * Get the OpenAPI specification describing the REST API provided by * this application. * * This method merges operations (HTTP endpoints) from the following sources: * - `app.api(spec)` * - `app.controller(MyController)` * - `app.route(route)` * - `app.route('get', '/greet', operationSpec, MyController, 'greet')` * * If the optional `requestContext` is provided, then the `servers` list * in the returned spec will be updated to work in that context. * Specifically: * 1. if `config.openApi.setServersFromRequest` is enabled, the servers * list will be replaced with the context base url * 2. Any `servers` entries with a path of `/` will have that path * replaced with `requestContext.basePath` * * @param requestContext - Optional context to update the `servers` list * in the returned spec */ getApiSpec(requestContext?: RequestContext): Promise; /** * Update or rebuild OpenAPI Spec object to be appropriate for the context of * a specific request for the spec, leveraging both app config and request * path information. * * @param spec base spec object from which to start * @param requestContext request to use to infer path information * @returns Updated or rebuilt spec object to use in the context of the request */ private updateSpecFromRequest; /** * Configure a custom sequence class for handling incoming requests. * * @example * ```ts * class MySequence implements SequenceHandler { * constructor( * @inject('send) public send: Send)) { * } * * public async handle({response}: RequestContext) { * send(response, 'hello world'); * } * } * ``` * * @param sequenceClass - The sequence class to invoke for each incoming request. */ sequence(sequenceClass: Constructor): Binding; /** * Configure a custom sequence function for handling incoming requests. * * @example * ```ts * app.handler(({request, response}, sequence) => { * sequence.send(response, 'hello world'); * }); * ``` * * @param handlerFn - The handler to invoke for each incoming request. */ handler(handlerFn: SequenceFunction): void; /** * Bind a body parser to the server context * @param parserClass - Body parser class * @param address - Optional binding address */ bodyParser(bodyParserClass: Constructor, address?: BindingAddress): Binding; /** * Configure the `basePath` for the rest server * @param path - Base path */ basePath(path?: string): void; /** * Start this REST API's HTTP/HTTPS server. */ start(): Promise; /** * Stop this REST API's HTTP/HTTPS server. */ stop(): Promise; /** * Mount an Express router to expose additional REST endpoints handled * via legacy Express-based stack. * * @param basePath - Path where to mount the router at, e.g. `/` or `/api`. * @param router - The Express router to handle the requests. * @param spec - A partial OpenAPI spec describing endpoints provided by the * router. LoopBack will prepend `basePath` to all endpoints automatically. * This argument is optional. You can leave it out if you don't want to * document the routes. */ mountExpressRouter(basePath: string, router: ExpressRequestHandler, spec?: RouterSpec): void; /** * Export the OpenAPI spec to the given json or yaml file * @param outFile - File name for the spec. The extension of the file * determines the format of the file. * - `yaml` or `yml`: YAML * - `json` or other: JSON * If the outFile is not provided or its value is `''` or `'-'`, the spec is * written to the console using the `log` function. * @param log - Log function, default to `console.log` */ exportOpenApiSpec(outFile?: string, log?: (message?: any, ...optionalParams: any[]) => void): Promise; } /** * Create a binding for the given body parser class * @param parserClass - Body parser class * @param key - Optional binding address */ export declare function createBodyParserBinding(parserClass: Constructor, key?: BindingAddress): Binding; /** * The form of OpenAPI specs to be served */ export interface OpenApiSpecForm { version?: string; format?: string; } /** * Options to customize how OpenAPI specs are served */ export interface OpenApiSpecOptions { /** * Mapping of urls to spec forms, by default: *
* { *
* '/openapi.json': {version: '3.0.0', format: 'json'}, *
* '/openapi.yaml': {version: '3.0.0', format: 'yaml'}, *
* } * */ endpointMapping?: { [key: string]: OpenApiSpecForm; }; /** * A flag to force `servers` to be set from the http request for the OpenAPI * spec */ setServersFromRequest?: boolean; /** * Configure servers for OpenAPI spec */ servers?: ServerObject[]; /** * Set this flag to disable the endpoint for OpenAPI spec */ disabled?: true; /** * Set this flag to `false` to disable OAS schema consolidation. If not set, * the value defaults to `true`. */ consolidate?: boolean; } export interface ApiExplorerOptions { /** * URL for the hosted API explorer UI * default to https://loopback.io/api-explorer */ url?: string; /** * URL for the API explorer served over `http` protocol to deal with mixed * content security imposed by browsers as the spec is exposed over `http` by * default. * See https://github.com/loopbackio/loopback-next/issues/1603 */ httpUrl?: string; /** * Set this flag to disable the built-in redirect to externally * hosted API Explorer UI. */ disabled?: true; } /** * RestServer options */ export declare type RestServerOptions = Partial; export interface RestServerResolvedOptions { port: number; path?: string; /** * Base path for API/static routes */ basePath?: string; cors: cors.CorsOptions; openApiSpec: OpenApiSpecOptions; apiExplorer: ApiExplorerOptions; requestBodyParser?: RequestBodyParserOptions; sequence?: Constructor; expressSettings: { [name: string]: any; }; router: RestRouterOptions; /** * Set this flag to `false` to not listen on connections when the REST server * is started. It's useful to mount a LoopBack REST server as a route to the * facade Express application. If not set, the value is default to `true`. */ listenOnStart?: boolean; } /** * Valid configuration for the RestServer constructor. */ export declare type RestServerConfig = RestServerOptions & HttpServerOptions; export declare type RestServerResolvedConfig = RestServerResolvedOptions & HttpServerOptions;