UNPKG

5.19 kBJavaScriptView Raw
1"use strict";
2// tslint:disable:prefer-function-over-method
3Object.defineProperty(exports, "__esModule", { value: true });
4const NewrelicUtil_1 = require("../newrelic/NewrelicUtil");
5const optionParsingRegExp = /^\s*([^\s]*)\s*\((.*)\)/;
6const optionParsingRegExp2 = /[a-zA-Z0-9?:@_-]+/g;
7const SWAGGER_CONTROLLER_PROPERTY = 'x-inceptum-controller';
8const SWAGGER_OPERATION_PROPERTY = 'x-inceptum-operation';
9const newrelic = NewrelicUtil_1.NewrelicUtil.getNewrelicIfAvailable();
10function assert(predicate, message) {
11 if (!predicate) {
12 throw new Error(message);
13 }
14}
15const getControllerName = (req) => req.swagger.operation[SWAGGER_CONTROLLER_PROPERTY]
16 ? req.swagger.operation[SWAGGER_CONTROLLER_PROPERTY]
17 : req.swagger.path[SWAGGER_CONTROLLER_PROPERTY];
18const getOperationName = (req) => req.swagger.operation[SWAGGER_OPERATION_PROPERTY]
19 ? req.swagger.operation[SWAGGER_OPERATION_PROPERTY]
20 : req.method.toLowerCase();
21class SwaggerRouterMiddleware {
22 constructor(context) {
23 this.context = context;
24 this.handlerCache = new Map();
25 }
26 hasController(req) {
27 if (!req || !req.swagger) {
28 return false;
29 }
30 if (req.swagger.operation && req.swagger.operation[SWAGGER_CONTROLLER_PROPERTY]) {
31 return true;
32 }
33 if (req.swagger.path && req.swagger.path[SWAGGER_CONTROLLER_PROPERTY]) {
34 return true;
35 }
36 return false;
37 }
38 async register(expressApp) {
39 expressApp.use(async (req, res, next) => {
40 if (newrelic && req.swagger && req.swagger.apiPath) {
41 // NR adds a `/` at the start of the path for us.
42 const basePath = req.swagger.swaggerObject.basePath.substring(1);
43 newrelic.setTransactionName(`${basePath}${req.swagger.apiPath}`);
44 }
45 try {
46 if (this.hasController(req)) {
47 const handler = await this.getControllerHandler(req);
48 assert(handler, `Could not find handler for ${getControllerName(req)}#${getOperationName(req)}. Make sure there is a matching class/method registered on the context.`);
49 try {
50 const resp = await handler(req, res);
51 assert(res.headersSent, `${getControllerName(req)}#${getOperationName(req)} was called but didn't handle the request. Make sure you always handle the request by calling an appopriate method on "res"`);
52 }
53 catch (error) {
54 next(error); // Send to express error handler
55 }
56 }
57 else {
58 next(); // Not handled, continue up the middleware chain
59 }
60 }
61 catch (e) {
62 next(e); // Send to express error handler
63 }
64 });
65 }
66 /**
67 * @private
68 * @param controllerName
69 * @returns {*}
70 */
71 getControllerObjectPromise(controllerName) {
72 return this.context.getObjectByName(controllerName);
73 }
74 /**
75 * @private
76 * @param req
77 * @returns Function
78 */
79 async getControllerHandler(req) {
80 const controllerName = getControllerName(req);
81 const operationId = getOperationName(req);
82 const key = `${controllerName}_${operationId}`;
83 if (this.handlerCache.has(key)) {
84 return this.handlerCache.get(key);
85 }
86 const controller = await this.getControllerObjectPromise(controllerName);
87 if (controller) {
88 const handler = this.createControllerArgHandler(controller, operationId);
89 if (handler) {
90 this.handlerCache.set(key, handler);
91 return handler;
92 }
93 }
94 }
95 /**
96 * @private
97 * @param controller
98 * @param operationId
99 * @returns {function(*=, *=)|null}
100 */
101 createControllerArgHandler(controller, operationId) {
102 let functionName;
103 let params = [];
104 if (operationId.indexOf('(') < 0) {
105 functionName = operationId.trim();
106 }
107 else {
108 const matches = operationId.match(optionParsingRegExp);
109 functionName = matches[1];
110 if (matches[2].trim().length > 0) {
111 params = matches[2].match(optionParsingRegExp2);
112 }
113 }
114 if (!controller[functionName]) {
115 return;
116 }
117 const paramFunctions = [];
118 params.forEach((param) => {
119 if (param === 'null') {
120 paramFunctions.push(() => null);
121 }
122 else {
123 paramFunctions.push((req) => req.swagger.params[param].value);
124 }
125 });
126 paramFunctions.push((req) => req);
127 paramFunctions.push((req, res) => res);
128 return (req, res) => {
129 controller.req = req;
130 controller.res = res;
131 const args = paramFunctions.map((f) => f(req, res));
132 return controller[functionName](...args);
133 };
134 }
135}
136exports.default = SwaggerRouterMiddleware;
137//# sourceMappingURL=SwaggerRouterMiddleware.js.map
\No newline at end of file