UNPKG

3.06 kBPlain TextView Raw
1// Copyright IBM Corp. and LoopBack contributors 2017,2020. All Rights Reserved.
2// Node module: @loopback/rest
3// This file is licensed under the MIT License.
4// License text available at https://opensource.org/licenses/MIT
5
6import {Context} from '@loopback/core';
7import {
8 ComponentsObject,
9 ControllerSpec,
10 PathObject,
11 ReferenceObject,
12 SchemaObject,
13 SchemasObject,
14} from '@loopback/openapi-v3';
15import {RestBindings} from './keys';
16import {RequestContext} from './request-context';
17import {RestServerResolvedConfig} from './rest.server';
18import {
19 ControllerClass,
20 ControllerFactory,
21 ResolvedRoute,
22 RouteEntry,
23 RoutingTable,
24} from './router';
25import {SequenceHandler} from './sequence';
26import {Request, Response} from './types';
27
28export class HttpHandler {
29 /**
30 * Shared OpenAPI spec objects as `components`
31 */
32 protected _openApiComponents: ComponentsObject;
33
34 public handleRequest: (request: Request, response: Response) => Promise<void>;
35
36 constructor(
37 protected readonly _rootContext: Context,
38 protected readonly _serverConfig: RestServerResolvedConfig,
39 protected readonly _routes = new RoutingTable(),
40 ) {
41 this.handleRequest = (req, res) => this._handleRequest(req, res);
42 }
43
44 registerController<T extends object>(
45 spec: ControllerSpec,
46 controllerCtor: ControllerClass<T>,
47 controllerFactory?: ControllerFactory<T>,
48 ) {
49 this._routes.registerController(spec, controllerCtor, controllerFactory);
50 }
51
52 registerRoute(route: RouteEntry) {
53 this._routes.registerRoute(route);
54 }
55
56 /**
57 * @deprecated Use `registerApiComponents`
58 * @param defs Schemas
59 */
60 registerApiDefinitions(defs: SchemasObject) {
61 this.registerApiComponents({schemas: defs});
62 }
63
64 /**
65 * Merge components into the OpenApi spec
66 * @param defs - Components
67 */
68 registerApiComponents(defs: ComponentsObject) {
69 this._openApiComponents = this._openApiComponents ?? {};
70 for (const p in defs) {
71 // Merge each child, such as `schemas`, `parameters`, and `headers`
72 this._openApiComponents[p] = {...this._openApiComponents[p], ...defs[p]};
73 }
74 }
75
76 getApiComponents() {
77 return this._openApiComponents;
78 }
79
80 /**
81 * @deprecated Use `getApiComponents`
82 */
83 getApiDefinitions():
84 | {
85 [schema: string]: SchemaObject | ReferenceObject;
86 }
87 | undefined {
88 return this._openApiComponents?.schemas;
89 }
90
91 describeApiPaths(): PathObject {
92 return this._routes.describeApiPaths();
93 }
94
95 findRoute(request: Request): ResolvedRoute {
96 const route = this._routes.find(request);
97 Object.assign(route.schemas, this.getApiDefinitions());
98 return route;
99 }
100
101 protected async _handleRequest(
102 request: Request,
103 response: Response,
104 ): Promise<void> {
105 const requestContext = new RequestContext(
106 request,
107 response,
108 this._rootContext,
109 this._serverConfig,
110 );
111
112 const sequence = await requestContext.get<SequenceHandler>(
113 RestBindings.SEQUENCE,
114 );
115 await sequence.handle(requestContext);
116 }
117}