UNPKG

bpframework

Version:

Web framework like java springboot and springcloud

430 lines 17.9 kB
'use strict'; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports._RestControllerPushRouter = exports._RestControllerDo = exports.CallRestControllerRoute = exports.RestController = exports.setRestControllerDefaultCfg = exports._RestControllerMetadataKey = void 0; require("reflect-metadata"); const febs = require("febs"); const Service_1 = require("../../Service"); const loggerRest_1 = require("../../../loggerRest"); const urlUtils_1 = require("../../../utils/urlUtils"); const objectUtils_1 = require("../../../utils/objectUtils"); const RequestConditional_1 = require("./RequestConditional"); var qs = require('../../../utils/qs/dist'); const DefaultRestControllerCfg = Symbol('DefaultRestControllerCfg'); const RestControllerRouters = Symbol('RestControllerRouters'); const _RestControllerRouterMetadataKey = Symbol('_RestControllerRouterMetadataKey'); exports._RestControllerMetadataKey = Symbol('_RestControllerMetadataKey'); function getRestControllerRouters() { let routers = global[RestControllerRouters]; if (!routers) { routers = []; global[RestControllerRouters] = routers; } return routers; } function setRestControllerDefaultCfg(cfg) { if (cfg.hasOwnProperty('logLevel')) { (0, loggerRest_1.setRestLoggerLevel)(cfg.logLevel); } let c = global[DefaultRestControllerCfg]; if (!c) { c = {}; global[DefaultRestControllerCfg] = c; } if (cfg.hasOwnProperty('beforeProcessRequestCallback')) { c.beforeProcessRequestCallback = cfg.beforeProcessRequestCallback; } if (cfg.hasOwnProperty('filterMessageCallback')) { c.filterMessageCallback = cfg.filterMessageCallback; } if (cfg.hasOwnProperty('errorRequestCallback')) { c.errorRequestCallback = cfg.errorRequestCallback; } if (cfg.hasOwnProperty('errorResponseCallback')) { c.errorResponseCallback = cfg.errorResponseCallback; } if (cfg.hasOwnProperty('notFoundCallback')) { c.notFoundCallback = cfg.notFoundCallback; } if (cfg.hasOwnProperty('headers')) { c.headers = febs.utils.mergeMap(cfg.headers); } } exports.setRestControllerDefaultCfg = setRestControllerDefaultCfg; function getRestControllerDefaultCfg() { let cfg = global[DefaultRestControllerCfg]; cfg = cfg || {}; return cfg; } function RestController(cfg) { cfg = cfg || {}; cfg.path = cfg.path || ''; let fooService = (0, Service_1.Service)(); return (target) => { fooService(target); let routers = Reflect.getOwnMetadata(_RestControllerRouterMetadataKey, target); if (routers) { let globalRouters = getRestControllerRouters(); for (let p in routers) { let val = routers[p]; let pp = urlUtils_1.default.join(cfg.path, val.path); let pps = pp.split('/'); pp = ''; for (let i in pps) { let ppsi = pps[i]; if (pp.length > 0 && pp[pp.length - 1] != '/') { pp += '/'; } if (ppsi.length != 0) { if (ppsi.length > 2) { if (ppsi[0] == '{' && ppsi[ppsi.length - 1] == '}') { pp += ppsi; } else { pp += encodeURIComponent(ppsi); } } else { pp += encodeURIComponent(ppsi); } } else if (pp.length == 0) { pp += '/'; } } let reg = getPathReg(pp, val.params); val.reg = reg.reg; val.pathVars = reg.pathVars; val.target = target; globalRouters.push(val); } } Reflect.defineMetadata(exports._RestControllerMetadataKey, {}, target); }; } exports.RestController = RestController; function CallRestControllerRoute(request, ctx) { return __awaiter(this, void 0, void 0, function* () { let interval = Date.now(); let rotuers = getRestControllerRouters(); if (!rotuers) { return Promise.resolve(null); } let pathname = request.url; let querystring = null; let qsPos = pathname.indexOf('?'); if (qsPos >= 0) { querystring = pathname.substr(qsPos + 1); if (!febs.string.isEmpty(querystring)) { querystring = qs.parse(querystring); for (let key in querystring) { if (typeof querystring[key] === 'string') { querystring[key] = decodeURIComponent(querystring[key]); } } } pathname = pathname.substr(0, qsPos); } let cfg = getRestControllerDefaultCfg(); let response = { headers: {}, status: 200, body: null, }; if (cfg.beforeProcessRequestCallback) { let r = cfg.beforeProcessRequestCallback(request, response); if (r instanceof Promise) { r = yield r; } if (!r) { return Promise.resolve(response); } } for (let i = 0; i < rotuers.length; i++) { let router = rotuers[i]; if (router.method == request.method.toLowerCase() && router.reg.test(pathname)) { let matchInfo = { match: true, requestError: null, responseError: null, isIgnoreRestLogger: false }; let ret; try { let target; if (router.serviceInstance) { target = router.serviceInstance; } else { target = router.serviceInstance = (0, Service_1.getServiceInstances)(router.target).instance; router.target = null; } let restObject = { request, response, responseMsg: null, error: null, ctx, }; let isBreak = false; let conditionals = (0, RequestConditional_1.getRequestConditional)(target.constructor, router.functionPropertyKey); for (let i = 0; i < conditionals.length; i++) { let conditional = conditionals[i]; if (!(yield conditional.match(restObject))) { isBreak = true; break; } } if (!isBreak) { ret = target[router.functionPropertyKey].call(target, { pathname: decodeURIComponent(pathname), querystring, request, response, params: router.params, pathVars: router.pathVars, }, matchInfo, ctx); if (ret instanceof Promise) { ret = yield ret; } } } catch (err) { matchInfo.responseError = err; } if (matchInfo.requestError) { response.status = 400; interval = Date.now() - interval; (0, loggerRest_1.logRest)(request, { err: '[Error] request error' }, interval); if (cfg.errorRequestCallback) { cfg.errorRequestCallback(matchInfo.requestError, request, response); } return Promise.resolve(response); } if (matchInfo.responseError) { response.status = 500; interval = Date.now() - interval; (0, loggerRest_1.logRest)(request, { err: '[Error] response error' }, interval); if (cfg.errorResponseCallback) { cfg.errorResponseCallback(matchInfo.responseError, request, response); } return Promise.resolve(response); } if (!matchInfo.match) { interval = Date.now() - interval; (0, loggerRest_1.logRest)(request, { err: '[404] Route matched, but condition not satisfied: ' + request.url }, interval); response.status = 404; if (cfg.notFoundCallback) { cfg.notFoundCallback(request, response); } return Promise.resolve(response); } if (!response.body) { if (cfg.filterMessageCallback) { ret = cfg.filterMessageCallback(ret, request.url); } response.body = JSON.stringify(ret, objectUtils_1.default.JSON_replacer); } interval = Date.now() - interval; if (!matchInfo.isIgnoreRestLogger) { (0, loggerRest_1.logRest)(request, response, interval); } return Promise.resolve(response); } } interval = Date.now() - interval; (0, loggerRest_1.logRest)(request, { err: '[404] Route is not match: ' + pathname }, interval); let response1 = { headers: {}, status: 404, body: null }; if (cfg.notFoundCallback) { const defaultHeaders = febs.utils.mergeMap(cfg.headers); if (defaultHeaders) { for (const key in defaultHeaders) { response1.headers[key] = defaultHeaders[key]; } } cfg.notFoundCallback(request, response1); } return Promise.resolve(response1); }); } exports.CallRestControllerRoute = CallRestControllerRoute; function _RestControllerDo(target, ctx, matchInfo, headers, castType, args, pathname, querystring, request, response, params, pathVars) { if (headers && typeof headers === 'function') { headers = headers(); } const defaultHeaders = febs.utils.mergeMap(getRestControllerDefaultCfg().headers, headers); if (defaultHeaders) { for (const key in defaultHeaders) { response.headers[key] = defaultHeaders[key]; } } args.length = 0; if (params) { for (let i in params) { let param = params[i]; if (args.length <= param.parameterIndex) { args.length = param.parameterIndex + 1; } if (param.type == 'pv') { let index = pathVars['{' + param.name + '}']; if (!febs.utils.isNull(index)) { let data = pathname.split('/')[index]; if (data) { data = decodeURIComponent(data); } else if (param.required) { matchInfo.requestError = new febs.exception(`parameter "${param.name}" is required`, febs.exception.PARAM, __filename, __line, __column); return false; } let datar = objectUtils_1.default.castType(data, param.castType, true); if (datar.e) { matchInfo.requestError = datar.e; return false; } else { args[param.parameterIndex] = datar.data; } } } else if (param.type == 'rb') { if (!request.body) { if (param.required) { matchInfo.requestError = new febs.exception(`requestBody is required`, febs.exception.PARAM, __filename, __line, __column); return false; } args[param.parameterIndex] = null; } else { let datar = objectUtils_1.default.castType(request.body, param.castType, false); if (datar.e) { matchInfo.requestError = datar.e; return false; } else { args[param.parameterIndex] = datar.data; } } } else if (param.type == 'rp') { if (!querystring || !querystring.hasOwnProperty(param.name)) { if (param.required && !param.defaultValue) { matchInfo.requestError = new febs.exception(`parameter "${param.name}" is required`, febs.exception.PARAM, __filename, __line, __column); return false; } args[param.parameterIndex] = param.defaultValue; } else { let data = querystring[param.name]; let datar = objectUtils_1.default.castType(data, param.castType, false); if (datar.e) { matchInfo.requestError = datar.e; return false; } else { args[param.parameterIndex] = datar.data; } } } else if (param.type == 'ro') { args[param.parameterIndex] = { request, response, responseMsg: null, error: null, ctx, }; } } } return true; } exports._RestControllerDo = _RestControllerDo; function getPathReg(p, params) { params = params || []; if (p[0] != '/') p = '/' + p; if (p[p.length - 1] == '/') p = p.substr(0, p.length - 1); p = febs.string.replace(p, '\\', '\\\\'); p = febs.string.replace(p, '[', '\['); p = febs.string.replace(p, ']', '\]'); p = febs.string.replace(p, '(', '\('); p = febs.string.replace(p, ')', '\)'); p = febs.string.replace(p, '{', '\{'); p = febs.string.replace(p, '}', '\}'); p = febs.string.replace(p, '|', '\|'); p = febs.string.replace(p, '^', '\^'); p = febs.string.replace(p, '?', '\?'); p = febs.string.replace(p, '.', '\.'); p = febs.string.replace(p, '+', '\+'); p = febs.string.replace(p, '*', '\*'); p = febs.string.replace(p, '$', '\$'); p = febs.string.replace(p, ':', '\:'); p = febs.string.replace(p, '-', '\-'); let pathVars = {}; let segs = p.split('/'); p = ''; let pvHadRequired = true; for (let i = 0; i < segs.length; i++) { if (segs[i].length == 0) continue; p += '(\\/'; if (/^\{[a-zA-Z\$_][a-zA-Z\d_]*\}$/.test(segs[i])) { p += "[\\w\\~\\!\\*\\(\\)\\-\\_\\'\\.\\%\\@\\$\\&\\+\\=\\[\\]\\;\\:\\,]+" + ")"; let j; for (j = 0; j < params.length; j++) { if (params[j].type == 'pv' && '{' + params[j].name + '}' == segs[i]) { if (!params[j].required) { pvHadRequired = false; p += '?'; } else if (!pvHadRequired) { throw new Error(`@PathVariable '${params[j].name}': required cannot be 'true', pre-pathVariable required=false`); } break; } } pathVars[segs[i]] = i; } else { p += segs[i] + ')'; } } p = '^' + p + '\\/?(\\?.*)?$'; return { reg: new RegExp(p), pathVars }; } function _RestControllerPushRouter(targetObject, target, cfg) { let routers = Reflect.getOwnMetadata(_RestControllerRouterMetadataKey, target) || []; if (Array.isArray(cfg.path)) { for (let i = 0; i < cfg.path.length; i++) { routers.push({ target: targetObject, serviceInstance: null, functionPropertyKey: cfg.functionPropertyKey, params: cfg.params, path: cfg.path[i], method: cfg.method.toLowerCase(), }); } } else { routers.push({ target: targetObject, serviceInstance: null, functionPropertyKey: cfg.functionPropertyKey, params: cfg.params, path: cfg.path, method: cfg.method.toLowerCase(), }); } Reflect.defineMetadata(_RestControllerRouterMetadataKey, routers, target); } exports._RestControllerPushRouter = _RestControllerPushRouter; //# sourceMappingURL=RestController.js.map