@mvx/mvc
Version:
@mvx/mvc is mvc framework on server, base on koa, @tsdi frameworks
409 lines (407 loc) • 22.3 kB
JavaScript
"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