UNPKG

9.9 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.MiddlewareModule = void 0;
4const common_1 = require("@nestjs/common");
5const request_method_enum_1 = require("@nestjs/common/enums/request-method.enum");
6const shared_utils_1 = require("@nestjs/common/utils/shared.utils");
7const invalid_middleware_exception_1 = require("../errors/exceptions/invalid-middleware.exception");
8const runtime_exception_1 = require("../errors/exceptions/runtime.exception");
9const context_id_factory_1 = require("../helpers/context-id-factory");
10const execution_context_host_1 = require("../helpers/execution-context-host");
11const constants_1 = require("../injector/constants");
12const request_constants_1 = require("../router/request/request-constants");
13const router_exception_filters_1 = require("../router/router-exception-filters");
14const router_proxy_1 = require("../router/router-proxy");
15const utils_1 = require("../router/utils");
16const builder_1 = require("./builder");
17const resolver_1 = require("./resolver");
18const route_info_path_extractor_1 = require("./route-info-path-extractor");
19const routes_mapper_1 = require("./routes-mapper");
20class MiddlewareModule {
21 constructor() {
22 this.routerProxy = new router_proxy_1.RouterProxy();
23 this.exceptionFiltersCache = new WeakMap();
24 this.logger = new common_1.Logger(MiddlewareModule.name);
25 }
26 async register(middlewareContainer, container, config, injector, httpAdapter, graphInspector, options) {
27 this.appOptions = options;
28 const appRef = container.getHttpAdapterRef();
29 this.routerExceptionFilter = new router_exception_filters_1.RouterExceptionFilters(container, config, appRef);
30 this.routesMapper = new routes_mapper_1.RoutesMapper(container);
31 this.resolver = new resolver_1.MiddlewareResolver(middlewareContainer, injector);
32 this.routeInfoPathExtractor = new route_info_path_extractor_1.RouteInfoPathExtractor(config);
33 this.injector = injector;
34 this.container = container;
35 this.httpAdapter = httpAdapter;
36 this.graphInspector = graphInspector;
37 const modules = container.getModules();
38 await this.resolveMiddleware(middlewareContainer, modules);
39 }
40 async resolveMiddleware(middlewareContainer, modules) {
41 const moduleEntries = [...modules.entries()];
42 const loadMiddlewareConfiguration = async ([moduleName, moduleRef]) => {
43 await this.loadConfiguration(middlewareContainer, moduleRef, moduleName);
44 await this.resolver.resolveInstances(moduleRef, moduleName);
45 };
46 await Promise.all(moduleEntries.map(loadMiddlewareConfiguration));
47 }
48 async loadConfiguration(middlewareContainer, moduleRef, moduleKey) {
49 const { instance } = moduleRef;
50 if (!instance.configure) {
51 return;
52 }
53 const middlewareBuilder = new builder_1.MiddlewareBuilder(this.routesMapper, this.httpAdapter, this.routeInfoPathExtractor);
54 try {
55 await instance.configure(middlewareBuilder);
56 }
57 catch (err) {
58 if (!this.appOptions.preview) {
59 throw err;
60 }
61 const warningMessage = `Warning! "${moduleRef.name}" module exposes a "configure" method that throws an exception in the preview mode` +
62 ` (possibly due to missing dependencies). Note: you can ignore this message, just be aware that some of those conditional middlewares will not be reflected in your graph.`;
63 this.logger.warn(warningMessage);
64 }
65 if (!(middlewareBuilder instanceof builder_1.MiddlewareBuilder)) {
66 return;
67 }
68 const config = middlewareBuilder.build();
69 middlewareContainer.insertConfig(config, moduleKey);
70 }
71 async registerMiddleware(middlewareContainer, applicationRef) {
72 const configs = middlewareContainer.getConfigurations();
73 const registerAllConfigs = async (moduleKey, middlewareConfig) => {
74 for (const config of middlewareConfig) {
75 await this.registerMiddlewareConfig(middlewareContainer, config, moduleKey, applicationRef);
76 }
77 };
78 const entriesSortedByDistance = [...configs.entries()].sort(([moduleA], [moduleB]) => {
79 return (this.container.getModuleByKey(moduleA).distance -
80 this.container.getModuleByKey(moduleB).distance);
81 });
82 for (const [moduleRef, moduleConfigurations] of entriesSortedByDistance) {
83 await registerAllConfigs(moduleRef, [...moduleConfigurations]);
84 }
85 }
86 async registerMiddlewareConfig(middlewareContainer, config, moduleKey, applicationRef) {
87 const { forRoutes } = config;
88 for (const routeInfo of forRoutes) {
89 await this.registerRouteMiddleware(middlewareContainer, routeInfo, config, moduleKey, applicationRef);
90 }
91 }
92 async registerRouteMiddleware(middlewareContainer, routeInfo, config, moduleKey, applicationRef) {
93 var _a;
94 const middlewareCollection = [].concat(config.middleware);
95 const moduleRef = this.container.getModuleByKey(moduleKey);
96 for (const metatype of middlewareCollection) {
97 const collection = middlewareContainer.getMiddlewareCollection(moduleKey);
98 const instanceWrapper = collection.get(metatype);
99 if ((0, shared_utils_1.isUndefined)(instanceWrapper)) {
100 throw new runtime_exception_1.RuntimeException();
101 }
102 if (instanceWrapper.isTransient) {
103 return;
104 }
105 this.graphInspector.insertClassNode(moduleRef, instanceWrapper, 'middleware');
106 const middlewareDefinition = {
107 type: 'middleware',
108 methodName: 'use',
109 className: instanceWrapper.name,
110 classNodeId: instanceWrapper.id,
111 metadata: {
112 key: routeInfo.path,
113 path: routeInfo.path,
114 requestMethod: (_a = request_method_enum_1.RequestMethod[routeInfo.method]) !== null && _a !== void 0 ? _a : 'ALL',
115 version: routeInfo.version,
116 },
117 };
118 this.graphInspector.insertEntrypointDefinition(middlewareDefinition, instanceWrapper.id);
119 await this.bindHandler(instanceWrapper, applicationRef, routeInfo, moduleRef, collection);
120 }
121 }
122 async bindHandler(wrapper, applicationRef, routeInfo, moduleRef, collection) {
123 const { instance, metatype } = wrapper;
124 if ((0, shared_utils_1.isUndefined)(instance === null || instance === void 0 ? void 0 : instance.use)) {
125 throw new invalid_middleware_exception_1.InvalidMiddlewareException(metatype.name);
126 }
127 const isStatic = wrapper.isDependencyTreeStatic();
128 if (isStatic) {
129 const proxy = await this.createProxy(instance);
130 return this.registerHandler(applicationRef, routeInfo, proxy);
131 }
132 const isTreeDurable = wrapper.isDependencyTreeDurable();
133 await this.registerHandler(applicationRef, routeInfo, async (req, res, next) => {
134 try {
135 const contextId = this.getContextId(req, isTreeDurable);
136 const contextInstance = await this.injector.loadPerContext(instance, moduleRef, collection, contextId);
137 const proxy = await this.createProxy(contextInstance, contextId);
138 return proxy(req, res, next);
139 }
140 catch (err) {
141 let exceptionsHandler = this.exceptionFiltersCache.get(instance.use);
142 if (!exceptionsHandler) {
143 exceptionsHandler = this.routerExceptionFilter.create(instance, instance.use, undefined);
144 this.exceptionFiltersCache.set(instance.use, exceptionsHandler);
145 }
146 const host = new execution_context_host_1.ExecutionContextHost([req, res, next]);
147 exceptionsHandler.next(err, host);
148 }
149 });
150 }
151 async createProxy(instance, contextId = constants_1.STATIC_CONTEXT) {
152 const exceptionsHandler = this.routerExceptionFilter.create(instance, instance.use, undefined, contextId);
153 const middleware = instance.use.bind(instance);
154 return this.routerProxy.createProxy(middleware, exceptionsHandler);
155 }
156 async registerHandler(applicationRef, routeInfo, proxy) {
157 const { method } = routeInfo;
158 const paths = this.routeInfoPathExtractor.extractPathsFrom(routeInfo);
159 const isMethodAll = (0, utils_1.isRequestMethodAll)(method);
160 const requestMethod = request_method_enum_1.RequestMethod[method];
161 const router = await applicationRef.createMiddlewareFactory(method);
162 const middlewareFunction = isMethodAll
163 ? proxy
164 : (req, res, next) => {
165 if (applicationRef.getRequestMethod(req) === requestMethod) {
166 return proxy(req, res, next);
167 }
168 return next();
169 };
170 paths.forEach(path => router(path, middlewareFunction));
171 }
172 getContextId(request, isTreeDurable) {
173 const contextId = context_id_factory_1.ContextIdFactory.getByRequest(request);
174 if (!request[request_constants_1.REQUEST_CONTEXT_ID]) {
175 Object.defineProperty(request, request_constants_1.REQUEST_CONTEXT_ID, {
176 value: contextId,
177 enumerable: false,
178 writable: false,
179 configurable: false,
180 });
181 const requestProviderValue = isTreeDurable ? contextId.payload : request;
182 this.container.registerRequestProvider(requestProviderValue, contextId);
183 }
184 return contextId;
185 }
186}
187exports.MiddlewareModule = MiddlewareModule;