UNPKG

8.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const constants_1 = require("@nestjs/common/constants");
4const exceptions_1 = require("@nestjs/common/exceptions");
5const logger_service_1 = require("@nestjs/common/services/logger.service");
6const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
7const pathToRegexp = require("path-to-regexp");
8const unknown_request_mapping_exception_1 = require("../errors/exceptions/unknown-request-mapping.exception");
9const guards_consumer_1 = require("../guards/guards-consumer");
10const guards_context_creator_1 = require("../guards/guards-context-creator");
11const context_id_factory_1 = require("../helpers/context-id-factory");
12const execution_context_host_1 = require("../helpers/execution-context-host");
13const messages_1 = require("../helpers/messages");
14const router_method_factory_1 = require("../helpers/router-method-factory");
15const constants_2 = require("../injector/constants");
16const interceptors_consumer_1 = require("../interceptors/interceptors-consumer");
17const interceptors_context_creator_1 = require("../interceptors/interceptors-context-creator");
18const pipes_consumer_1 = require("../pipes/pipes-consumer");
19const pipes_context_creator_1 = require("../pipes/pipes-context-creator");
20const request_constants_1 = require("./request/request-constants");
21const route_params_factory_1 = require("./route-params-factory");
22const router_execution_context_1 = require("./router-execution-context");
23class RouterExplorer {
24 constructor(metadataScanner, container, injector, routerProxy, exceptionsFilter, config) {
25 this.metadataScanner = metadataScanner;
26 this.container = container;
27 this.injector = injector;
28 this.routerProxy = routerProxy;
29 this.exceptionsFilter = exceptionsFilter;
30 this.routerMethodFactory = new router_method_factory_1.RouterMethodFactory();
31 this.logger = new logger_service_1.Logger(RouterExplorer.name, true);
32 this.exceptionFiltersCache = new WeakMap();
33 this.executionContextCreator = new router_execution_context_1.RouterExecutionContext(new route_params_factory_1.RouteParamsFactory(), new pipes_context_creator_1.PipesContextCreator(container, config), new pipes_consumer_1.PipesConsumer(), new guards_context_creator_1.GuardsContextCreator(container, config), new guards_consumer_1.GuardsConsumer(), new interceptors_context_creator_1.InterceptorsContextCreator(container, config), new interceptors_consumer_1.InterceptorsConsumer(), container.getHttpAdapterRef());
34 }
35 explore(instanceWrapper, module, applicationRef, basePath, host) {
36 const { instance } = instanceWrapper;
37 const routerPaths = this.scanForPaths(instance);
38 this.applyPathsToRouterProxy(applicationRef, routerPaths, instanceWrapper, module, basePath, host);
39 }
40 extractRouterPath(metatype, prefix) {
41 let path = Reflect.getMetadata(constants_1.PATH_METADATA, metatype);
42 if (prefix)
43 path = prefix + this.validateRoutePath(path);
44 return this.validateRoutePath(path);
45 }
46 validateRoutePath(path) {
47 if (shared_utils_1.isUndefined(path)) {
48 throw new unknown_request_mapping_exception_1.UnknownRequestMappingException();
49 }
50 return shared_utils_1.validatePath(path);
51 }
52 scanForPaths(instance, prototype) {
53 const instancePrototype = shared_utils_1.isUndefined(prototype)
54 ? Object.getPrototypeOf(instance)
55 : prototype;
56 return this.metadataScanner.scanFromPrototype(instance, instancePrototype, method => this.exploreMethodMetadata(instance, instancePrototype, method));
57 }
58 exploreMethodMetadata(instance, instancePrototype, methodName) {
59 const targetCallback = instancePrototype[methodName];
60 const routePath = Reflect.getMetadata(constants_1.PATH_METADATA, targetCallback);
61 if (shared_utils_1.isUndefined(routePath)) {
62 return null;
63 }
64 const requestMethod = Reflect.getMetadata(constants_1.METHOD_METADATA, targetCallback);
65 const path = shared_utils_1.isString(routePath)
66 ? [this.validateRoutePath(routePath)]
67 : routePath.map(p => this.validateRoutePath(p));
68 return {
69 path,
70 requestMethod,
71 targetCallback,
72 methodName,
73 };
74 }
75 applyPathsToRouterProxy(router, routePaths, instanceWrapper, module, basePath, host) {
76 (routePaths || []).forEach(pathProperties => {
77 const { path, requestMethod } = pathProperties;
78 this.applyCallbackToRouter(router, pathProperties, instanceWrapper, module, basePath, host);
79 path.forEach(p => this.logger.log(messages_1.ROUTE_MAPPED_MESSAGE(p, requestMethod)));
80 });
81 }
82 applyCallbackToRouter(router, pathProperties, instanceWrapper, moduleKey, basePath, host) {
83 const { path: paths, requestMethod, targetCallback, methodName, } = pathProperties;
84 const { instance } = instanceWrapper;
85 const routerMethod = this.routerMethodFactory
86 .get(router, requestMethod)
87 .bind(router);
88 const stripSlash = (str) => str[str.length - 1] === '/' ? str.slice(0, str.length - 1) : str;
89 const isRequestScoped = !instanceWrapper.isDependencyTreeStatic();
90 const proxy = isRequestScoped
91 ? this.createRequestScopedHandler(instanceWrapper, requestMethod, this.container.getModuleByKey(moduleKey), moduleKey, methodName)
92 : this.createCallbackProxy(instance, targetCallback, methodName, moduleKey, requestMethod);
93 const hostHandler = this.applyHostFilter(host, proxy);
94 paths.forEach(path => {
95 const fullPath = stripSlash(basePath) + path;
96 routerMethod(stripSlash(fullPath) || '/', hostHandler);
97 });
98 }
99 applyHostFilter(host, handler) {
100 if (!host) {
101 return handler;
102 }
103 const httpAdapterRef = this.container.getHttpAdapterRef();
104 const keys = [];
105 const re = pathToRegexp(host, keys);
106 return (req, res, next) => {
107 req.hosts = {};
108 const hostname = httpAdapterRef.getRequestHostname(req) || '';
109 const match = hostname.match(re);
110 if (match) {
111 keys.forEach((key, i) => (req.hosts[key.name] = match[i + 1]));
112 return handler(req, res, next);
113 }
114 if (!next) {
115 throw new exceptions_1.InternalServerErrorException(`HTTP adapter does not support filtering on host: "${host}"`);
116 }
117 return next();
118 };
119 }
120 createCallbackProxy(instance, callback, methodName, module, requestMethod, contextId = constants_2.STATIC_CONTEXT, inquirerId) {
121 const executionContext = this.executionContextCreator.create(instance, callback, methodName, module, requestMethod, contextId, inquirerId);
122 const exceptionFilter = this.exceptionsFilter.create(instance, callback, module, contextId, inquirerId);
123 return this.routerProxy.createProxy(executionContext, exceptionFilter);
124 }
125 createRequestScopedHandler(instanceWrapper, requestMethod, module, moduleKey, methodName) {
126 const { instance } = instanceWrapper;
127 const collection = module.controllers;
128 return async (req, res, next) => {
129 try {
130 const contextId = this.getContextId(req);
131 const contextInstance = await this.injector.loadPerContext(instance, module, collection, contextId);
132 await this.createCallbackProxy(contextInstance, contextInstance[methodName], methodName, moduleKey, requestMethod, contextId, instanceWrapper.id)(req, res, next);
133 }
134 catch (err) {
135 let exceptionFilter = this.exceptionFiltersCache.get(instance[methodName]);
136 if (!exceptionFilter) {
137 exceptionFilter = this.exceptionsFilter.create(instance, instance[methodName], moduleKey);
138 this.exceptionFiltersCache.set(instance[methodName], exceptionFilter);
139 }
140 const host = new execution_context_host_1.ExecutionContextHost([req, res, next]);
141 exceptionFilter.next(err, host);
142 }
143 };
144 }
145 getContextId(request) {
146 const contextId = context_id_factory_1.ContextIdFactory.getByRequest(request);
147 if (!request[request_constants_1.REQUEST_CONTEXT_ID]) {
148 Object.defineProperty(request, request_constants_1.REQUEST_CONTEXT_ID, {
149 value: contextId,
150 enumerable: false,
151 writable: false,
152 configurable: false,
153 });
154 this.container.registerRequestProvider(request, contextId);
155 }
156 return contextId;
157 }
158}
159exports.RouterExplorer = RouterExplorer;