UNPKG

@mvx/mvc

Version:

@mvx/mvc is mvc framework on server, base on koa, @tsdi frameworks

409 lines (407 loc) 22.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ControllerRoute = exports.RouteControllerMiddlewaresToken = exports.RouteControllerArgToken = exports.isBuffer = void 0; var tslib_1 = require("tslib"); var ioc_1 = require("@tsdi/ioc"); var boot_1 = require("@tsdi/boot"); var IContext_1 = require("../IContext"); var RequestMethod_1 = require("../RequestMethod"); var errors_1 = require("../errors"); var ResultValue_1 = require("../results/ResultValue"); var decorators_1 = require("../decorators"); var AuthorizationService_1 = require("../services/AuthorizationService"); var Route_1 = require("./Route"); var MvcMiddleware_1 = require("../middlewares/MvcMiddleware"); var MvcMiddlewares_1 = require("../middlewares/MvcMiddlewares"); var vary = require('vary'); function isBuffer(target) { if (typeof Buffer === 'undefined') { return false; } else { return ioc_1.lang.getClass(target) === Buffer; } } exports.isBuffer = isBuffer; var emptyNext = function () { return tslib_1.__awaiter(void 0, void 0, void 0, function () { return tslib_1.__generator(this, function (_a) { return [2 /*return*/]; }); }); }; exports.RouteControllerArgToken = ioc_1.tokenId('ROUTE_CONTRL_ARGS'); exports.RouteControllerMiddlewaresToken = ioc_1.tokenId('ROUTE_CONTRL_MIDDLEWARES'); var restParms = /^\S*:/; var isRest = /\/:/; var ControllerRoute = /** @class */ (function (_super) { tslib_1.__extends(ControllerRoute, _super); function ControllerRoute(url, controller, middlewares) { var _this = _super.call(this, url) || this; _this.controller = controller; _this.middlewares = middlewares; return _this; } ControllerRoute.prototype.navigate = function (ctx, next) { if (ctx._isCors) { return this.options(ctx, next); } else { return this.navigating(ctx, next); } }; ControllerRoute.prototype.navigating = function (ctx, next) { return tslib_1.__awaiter(this, void 0, void 0, function () { var meta, middlewares; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: meta = this.getRouteMetaData(ctx, RequestMethod_1.parseRequestMethod(ctx.method)); if (!!meta) return [3 /*break*/, 2]; return [4 /*yield*/, next()]; case 1: return [2 /*return*/, _a.sent()]; case 2: middlewares = this.getRouteMiddleware(ctx, meta); if (!middlewares.length) return [3 /*break*/, 4]; return [4 /*yield*/, this.execFuncs(ctx, middlewares.map(function (m) { return _this.toHandle(m); }).filter(function (f) { return !!f; }))]; case 3: _a.sent(); _a.label = 4; case 4: return [4 /*yield*/, this.invoke(ctx, meta)]; case 5: _a.sent(); return [4 /*yield*/, next()]; case 6: return [2 /*return*/, _a.sent()]; } }); }); }; ControllerRoute.prototype.getRouteMiddleware = function (ctx, meta) { var _this = this; var auths = ctx.getInjector().getServices(AuthorizationService_1.AuthorizationService); var middlewares = this.middlewares || []; if (auths) { middlewares = auths.map(function (auth) { return auth.getAuthMiddlewares(ctx, _this.controller); }).reduce(function (p, c) { return p.concat(c); }, []) .concat(middlewares) .concat(auths.map(function (a) { return a.getAuthMiddlewares(ctx, _this.controller, meta.propertyKey); }).reduce(function (p, c) { return p.concat(c); }, [])); } if (meta.middlewares) { middlewares = middlewares.concat(meta.middlewares); } return middlewares; }; ControllerRoute.prototype.options = function (ctx, next) { var _a, _b; return tslib_1.__awaiter(this, void 0, void 0, function () { var requestOrigin, config, options, origin, headersSet, set, err_1, errHeadersSet, varyWithOrigin, coremeta, maxAge, allowsM, allowH; return tslib_1.__generator(this, function (_c) { switch (_c.label) { case 0: requestOrigin = ctx.get('Origin'); ctx.vary('Origin'); if (!!requestOrigin) return [3 /*break*/, 2]; return [4 /*yield*/, next()]; case 1: return [2 /*return*/, _c.sent()]; case 2: config = ctx.mvcContext.getConfiguration(); options = config.corsOptions || {}; if (!ioc_1.isFunction(options.origin)) return [3 /*break*/, 7]; origin = options.origin(ctx); if (!ioc_1.isPromise(origin)) return [3 /*break*/, 4]; return [4 /*yield*/, origin]; case 3: origin = _c.sent(); _c.label = 4; case 4: if (!!origin) return [3 /*break*/, 6]; return [4 /*yield*/, next()]; case 5: return [2 /*return*/, _c.sent()]; case 6: return [3 /*break*/, 8]; case 7: origin = options.origin || requestOrigin; _c.label = 8; case 8: headersSet = {}; set = function (key, value) { ctx.set(key, value); headersSet[key] = value; }; if (!(ctx.method !== 'OPTIONS')) return [3 /*break*/, 14]; set('Access-Control-Allow-Origin', origin); if (options.credentials === true) { set('Access-Control-Allow-Credentials', 'true'); } if (options.exposeHeaders) { set('Access-Control-Expose-Headers', options.exposeHeaders); } if (!!options.keepHeadersOnError) return [3 /*break*/, 10]; return [4 /*yield*/, next()]; case 9: return [2 /*return*/, _c.sent()]; case 10: _c.trys.push([10, 12, , 13]); return [4 /*yield*/, next()]; case 11: _c.sent(); return [3 /*break*/, 13]; case 12: err_1 = _c.sent(); errHeadersSet = err_1.headers || {}; varyWithOrigin = vary.append(errHeadersSet.vary || errHeadersSet.Vary || '', 'Origin'); delete errHeadersSet.Vary; err_1.headers = tslib_1.__assign(tslib_1.__assign(tslib_1.__assign({}, errHeadersSet), headersSet), { vary: varyWithOrigin }); ctx.status = err_1 instanceof errors_1.HttpError ? err_1.status || 500 : 500; ctx.message = err_1.message || err_1.toString() || ''; (_b = (_a = ctx.mvcContext.getLogManager()) === null || _a === void 0 ? void 0 : _a.getLogger()) === null || _b === void 0 ? void 0 : _b.error(err_1); return [3 /*break*/, 13]; case 13: ; return [3 /*break*/, 17]; case 14: coremeta = this.getCorsMeta(ctx, ctx.get('Access-Control-Request-Method')); if (!!coremeta) return [3 /*break*/, 16]; ctx.status = 403; return [4 /*yield*/, next()]; case 15: return [2 /*return*/, _c.sent()]; case 16: options = tslib_1.__assign(tslib_1.__assign({}, options), coremeta); ctx.set('Access-Control-Allow-Origin', origin); if (options.credentials === true) { ctx.set('Access-Control-Allow-Credentials', 'true'); } maxAge = String(options.maxAge); if (maxAge) { ctx.set('Access-Control-Max-Age', maxAge); } allowsM = ioc_1.isArray(options.allowMethods) ? options.allowMethods.map(function (m) { return RequestMethod_1.methodToString(m); }).filter(function (m) { return !!m; }).join(',') : options.allowMethods; if (allowsM) { ctx.set('Access-Control-Allow-Methods', allowsM); } allowH = ioc_1.isArray(options.allowHeaders) ? options.allowHeaders.filter(function (m) { return !!m; }).join(',') : options.allowHeaders; if (!allowH) { allowH = ctx.get('Access-Control-Request-Headers'); } if (allowH) { ctx.set('Access-Control-Allow-Headers', allowH); } ctx.status = 204; _c.label = 17; case 17: return [2 /*return*/]; } }); }); }; ControllerRoute.prototype.getCorsMeta = function (ctx, reqMethod) { if (!reqMethod) { return null; } var method = RequestMethod_1.parseRequestMethod(reqMethod); var meta = this.getRouteMetaData(ctx, method); if (meta && meta.propertyKey) { var corsmetas = ioc_1.getMethodMetadata(decorators_1.Cors, this.controller)[meta.propertyKey.toString()] || []; if (corsmetas.length < 1) { corsmetas = ioc_1.getTypeMetadata(decorators_1.Cors, this.controller); } if (corsmetas.length) { return corsmetas.find(function (cor) { if (!cor.allowMethods) { return true; } if (cor.allowMethods) { if (ioc_1.isString(cor.allowMethods)) { return cor.allowMethods.toUpperCase().indexOf(reqMethod) >= 0; } else if (ioc_1.isArray(cor.allowMethods)) { return cor.allowMethods.some(function (c) { return RequestMethod_1.methodToString(c) === reqMethod; }); } } return false; }); } } return null; }; ControllerRoute.prototype.invoke = function (ctx, meta) { return tslib_1.__awaiter(this, void 0, void 0, function () { var injector, ctrl, reflects, providers, result; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: injector = ctx.mvcContext.injector; if (!(meta && meta.propertyKey)) return [3 /*break*/, 14]; ctrl = injector.getInstance(this.controller, { provide: IContext_1.ContextToken, useValue: ctx }); reflects = ctx.mvcContext.reflects; return [4 /*yield*/, this.createProvider(ctx, ctrl, meta, reflects.getParameters(this.controller, ctrl, meta.propertyKey))]; case 1: providers = _a.sent(); return [4 /*yield*/, injector.invoke.apply(injector, tslib_1.__spreadArrays([ctrl, meta.propertyKey], providers))]; case 2: result = _a.sent(); if (!ioc_1.isPromise(result)) return [3 /*break*/, 4]; return [4 /*yield*/, result]; case 3: result = _a.sent(); _a.label = 4; case 4: if (!ioc_1.isFunction(result)) return [3 /*break*/, 6]; return [4 /*yield*/, result(ctx)]; case 5: _a.sent(); return [3 /*break*/, 14]; case 6: if (!(result instanceof MvcMiddleware_1.MvcMiddleware || result instanceof MvcMiddlewares_1.MvcMiddlewares)) return [3 /*break*/, 8]; return [4 /*yield*/, result.execute(ctx, emptyNext)]; case 7: _a.sent(); return [3 /*break*/, 14]; case 8: if (!(ioc_1.isBaseType(result) || ioc_1.isArray(result) || isBuffer(result))) return [3 /*break*/, 9]; if (isBuffer(result)) { if (typeof Buffer !== 'undefined') { ctx.body = Buffer.from(result); } else { ctx.body = result; } } else { ctx.body = result; } ctx.status = 200; return [3 /*break*/, 14]; case 9: if (!ioc_1.isObject(result)) return [3 /*break*/, 13]; if (!(result instanceof ResultValue_1.ResultValue)) return [3 /*break*/, 11]; return [4 /*yield*/, result.sendValue(ctx)]; case 10: _a.sent(); return [3 /*break*/, 12]; case 11: ctx.body = result; ctx.status = 200; _a.label = 12; case 12: return [3 /*break*/, 14]; case 13: ctx.body = result; ctx.status = 200; _a.label = 14; case 14: return [2 /*return*/]; } }); }); }; ControllerRoute.prototype.createProvider = function (ctx, ctrl, meta, params) { return tslib_1.__awaiter(this, void 0, void 0, function () { var injector, providers, restParams_1, routes_1, restParamNames, baseURL, routeUrls_1, body_1, parser_1, ppds; var _this = this; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: injector = ctx.getInjector(); providers = [{ provide: IContext_1.ContextToken, useValue: ctx }]; if (!(params && params.length)) return [3 /*break*/, 2]; restParams_1 = {}; if (this.isRestUri(meta.route)) { routes_1 = meta.route.split('/').map(function (r) { return r.trim(); }); restParamNames = routes_1.filter(function (d) { return restParms.test(d); }); baseURL = this.vaildify(this.url, true); routeUrls_1 = this.vaildify(ctx.url.replace(baseURL, '')).split('/'); restParamNames.forEach(function (pname) { var val = routeUrls_1[routes_1.indexOf(pname)]; restParams_1[pname.substring(1)] = val; }); } body_1 = ctx.request.body || {}; parser_1 = injector.get(boot_1.BaseTypeParserToken); return [4 /*yield*/, Promise.all(params.map(function (param) { return tslib_1.__awaiter(_this, void 0, void 0, function () { var ptype, val, paramVal, mdparser; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: ptype = param.provider ? injector.getTokenProvider(param.provider) : param.type; if (!ioc_1.isFunction(ptype)) return [3 /*break*/, 5]; if (ioc_1.isBaseType(ptype)) { paramVal = restParams_1[param.name]; if (ioc_1.isUndefined(paramVal)) { paramVal = ctx.request.query[param.name]; } val = parser_1.parse(ptype, paramVal); } if (!(ioc_1.isNullOrUndefined(val) && ioc_1.lang.hasField(body_1))) return [3 /*break*/, 5]; if (!(ioc_1.isArray(ptype) && ioc_1.isArray(body_1))) return [3 /*break*/, 1]; val = body_1; return [3 /*break*/, 5]; case 1: if (!ioc_1.isBaseType(ptype)) return [3 /*break*/, 2]; val = parser_1.parse(ptype, body_1[param.name]); return [3 /*break*/, 5]; case 2: if (!ioc_1.isClass(ptype)) return [3 /*break*/, 5]; mdparser = injector.getService({ token: boot_1.ModelParser, target: tslib_1.__spreadArrays([ptype], ctx.mvcContext.reflects.getDecorators(ptype)), defaultToken: boot_1.DefaultModelParserToken }); if (!mdparser) return [3 /*break*/, 3]; val = mdparser.parseModel(ptype, body_1); return [3 /*break*/, 5]; case 3: return [4 /*yield*/, injector.getInstance(boot_1.BuilderServiceToken).resolve({ type: ptype, template: body_1 })]; case 4: val = _a.sent(); _a.label = 5; case 5: if (ioc_1.isNullOrUndefined(val)) { return [2 /*return*/, null]; } return [2 /*return*/, { provide: param.name || ptype, useValue: val }]; } }); }); }))]; case 1: ppds = _a.sent(); providers = providers.concat(ppds.filter(function (p) { return p !== null; })); _a.label = 2; case 2: return [2 /*return*/, providers]; } }); }); }; ControllerRoute.prototype.isRestUri = function (uri) { return isRest.test(uri || ''); }; ControllerRoute.prototype.getRouteMetaData = function (ctx, requestMethod) { var _this = this; var decoratorName = decorators_1.Route.toString(); var subRoute = this.vaildify(this.getReqRoute(ctx).replace(this.url, ''), true); var methodMaps = ioc_1.getMethodMetadata(decoratorName, this.controller); var meta; var allMethods = []; for (var name_1 in methodMaps) { allMethods = allMethods.concat(methodMaps[name_1]); } allMethods = allMethods.filter(function (m) { return m && m.method === requestMethod; }); allMethods = allMethods.sort(function (ra, rb) { return (rb.route || '').length - (ra.route || '').length; }); meta = allMethods.find(function (route) { return _this.vaildify(route.route || '', true) === subRoute; }); if (!meta) { meta = allMethods.find(function (route) { var uri = _this.vaildify(route.route || '', true); if (_this.isRestUri(uri)) { var idex = uri.indexOf('/:'); var url = uri.substring(0, idex); if (url !== subRoute && subRoute.indexOf(url) === 0) { return true; } } return false; }); } return meta; }; ControllerRoute.ρAnn = function () { return { "name": "ControllerRoute", "params": { "constructor": ["url", "controller", "middlewares"], "navigate": ["ctx", "next"], "navigating": ["ctx", "next"], "getRouteMiddleware": ["ctx", "meta"], "options": ["ctx", "next"], "getCorsMeta": ["ctx", "reqMethod"], "invoke": ["ctx", "meta"], "createProvider": ["ctx", "ctrl", "meta", "params"], "isRestUri": ["uri"], "getRouteMetaData": ["ctx", "requestMethod"] } }; }; ControllerRoute = tslib_1.__decorate([ ioc_1.Injectable(), tslib_1.__param(0, ioc_1.Inject(Route_1.RouteUrlArgToken)), tslib_1.__param(1, ioc_1.Inject(exports.RouteControllerArgToken)), tslib_1.__param(2, ioc_1.Inject(exports.RouteControllerMiddlewaresToken)), tslib_1.__metadata("design:paramtypes", [String, Object, Array]) ], ControllerRoute); return ControllerRoute; }(Route_1.MvcRoute)); exports.ControllerRoute = ControllerRoute; //# sourceMappingURL=../sourcemaps/router/ControllerRoute.js.map