UNPKG

sardines-service-provider-http

Version:
606 lines (605 loc) 32.5 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (this && this.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); }; 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()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.summaryServiceSettings = exports.defaultHttpServiceSettings = void 0; var Server = require("./server"); var sardines_core_1 = require("sardines-core"); var KoaSend = require("koa-send"); var fs = require("fs"); exports.defaultHttpServiceSettings = { protocol: sardines_core_1.Http.Protocol.HTTP, path: '/', method: sardines_core_1.Http.Method.POST, inputParameters: [{ position: sardines_core_1.Http.ServiceInputParamPosition.body, type: sardines_core_1.Http.ServiceInputParamType.object }], middlewares: [], postProcesses: [], response: { type: sardines_core_1.Http.ServiceResponseType.json } }; exports.summaryServiceSettings = function (serviceSettings) { return serviceSettings.protocol.toUpperCase() + "@" + serviceSettings.method + ":" + serviceSettings.path; }; var joinPath = function (root, servicePath) { return ("" + root + Server.validatePath(servicePath)).replace(/\/+/g, '/'); }; var unifyHttpServiceSettings = function (originalServiceSettings, serverSettings) { var serviceSettings = Object.assign({}, originalServiceSettings); if (!serviceSettings.protocol) serviceSettings.protocol = sardines_core_1.Http.Protocol.HTTP; if (!serviceSettings.method) serviceSettings.method = sardines_core_1.Http.Method.POST; if (!serviceSettings.response) serviceSettings.response = { type: sardines_core_1.Http.ServiceResponseType.json }; if (!serviceSettings.response.type) serviceSettings.response.type = sardines_core_1.Http.ServiceResponseType.json; serviceSettings.protocol = sardines_core_1.Http.Protocol[serviceSettings.protocol.toUpperCase()]; serviceSettings.method = sardines_core_1.Http.Method[serviceSettings.method.toUpperCase()]; serviceSettings.response.type = sardines_core_1.Http.ServiceResponseType[serviceSettings.response.type.toLowerCase()]; if (!serviceSettings.response.type) { serviceSettings.response.type = sardines_core_1.Http.ServiceResponseType.json; } serviceSettings.path = joinPath(serverSettings.root, serviceSettings.path); if (serviceSettings.response.type === sardines_core_1.Http.ServiceResponseType.static || serviceSettings.response.type === sardines_core_1.Http.ServiceResponseType.file) { if (!(serviceSettings.response.path)) { serviceSettings.response.path = './'; } if (serviceSettings.path[serviceSettings.path.length - 1] !== '*') { if (serviceSettings.path[serviceSettings.path.length - 1] !== '/') { serviceSettings.path += '/'; } serviceSettings.path += '*'; } } if (serviceSettings.inputParameters && Array.isArray(serviceSettings.inputParameters) && serviceSettings.inputParameters.length) { for (var _i = 0, _a = serviceSettings.inputParameters; _i < _a.length; _i++) { var paramDef = _a[_i]; if (paramDef.position) { paramDef.position = sardines_core_1.Http.ServiceInputParamPosition[paramDef.position.toLowerCase()]; } if (!paramDef.position) { paramDef.position = sardines_core_1.Http.ServiceInputParamPosition.body; } if (paramDef.type) { paramDef.type = sardines_core_1.Http.ServiceInputParamType[paramDef.type.toLowerCase()]; } if (!paramDef.type) { paramDef.type = sardines_core_1.Http.ServiceInputParamType.object; } if (typeof paramDef.name === 'undefined') { paramDef.name = ''; } } } var serviceSummary = exports.summaryServiceSettings(serviceSettings); serviceSettings.summary = serviceSummary; if (!(serviceSettings.protocol.toUpperCase() in sardines_core_1.Http.Protocol)) { return "Invalid protocol <" + serviceSettings.protocol + "> for registering service [" + serviceSummary + "]"; } if (!(serviceSettings.method.toUpperCase() in sardines_core_1.Http.Method)) { return "Invalid method <" + serviceSettings.method + "> for registering service [" + serviceSummary + "]"; } return serviceSettings; }; var unifyServiceSettings = function (application, service, serverSettings, additionalSettings, handler) { var httpService = {}; var serviceId = ("/" + application + "/" + service.module + "/" + service.name).replace(/\/+/g, '/'); if (additionalSettings && additionalSettings.path) httpService.path = additionalSettings.path; else httpService.path = serviceId; if (additionalSettings && additionalSettings.root) httpService.root = additionalSettings.root; httpService.protocol = serverSettings.protocol; if (additionalSettings && additionalSettings.method) httpService.method = additionalSettings.method; else httpService.method = sardines_core_1.Http.Method.POST; if (service.arguments && Array.isArray(service.arguments) && service.arguments.length > 0) { var i = 0; var additionArgSettings = null; if (additionalSettings && additionalSettings.arguments) additionArgSettings = additionalSettings.arguments; else if (additionalSettings && additionalSettings.inputParameters) additionArgSettings = additionalSettings.inputParameters; var additionArgSettingsCache = null; if (additionArgSettings) { additionArgSettingsCache = {}; for (var _i = 0, additionArgSettings_1 = additionArgSettings; _i < additionArgSettings_1.length; _i++) { var arg = additionArgSettings_1[_i]; if (arg.name) additionArgSettingsCache[arg.name] = arg; } } for (var _a = 0, _b = service.arguments; _a < _b.length; _a++) { var arg = _b[_a]; if (!httpService.inputParameters) httpService.inputParameters = []; var additionArg = null; if (additionArgSettings) { if (additionArgSettings.length === service.arguments.length) { additionArg = additionArgSettings[i]; } else if (arg.name && additionArgSettingsCache) { additionArg = additionArgSettingsCache[arg.name]; } } if (!additionArg) httpService.inputParameters.push(arg); else httpService.inputParameters.push(Object.assign({}, arg, additionArg)); i++; } } if (additionalSettings && additionalSettings.response) { httpService.response = additionalSettings.response; } else if (service.returnType) { httpService.response = { type: service.returnType }; } if (handler) httpService.handler = handler; return unifyHttpServiceSettings(httpService, serverSettings); }; var readFile = function (filepath) { return (new Promise(function (rfRes, rfRej) { fs.readFile(filepath, { encoding: 'utf8' }, function (err, data) { if (err) { rfRej({ status: 404, message: "File not found: " + filepath }); } else { rfRes(data); } }); })); }; var extractParams = function (ctx, paramDef) { return new Promise(function (resolve, reject) { var parameters = []; var pd = paramDef || [{ position: sardines_core_1.Http.ServiceInputParamPosition.body, type: sardines_core_1.Http.ServiceInputParamType.object, name: '' }]; if (pd && Array.isArray(pd) && pd.length > 0) { pd.forEach(function (p) { if (typeof p === 'object' && p.position && (typeof p.name === 'string' || p.name === undefined)) { var param = Object.assign({}, { position: 'body', type: 'object', name: '' }, p); switch (param.position) { case sardines_core_1.Http.ServiceInputParamPosition.ctx: if (param.name === undefined || param.name === '') { parameters.push(ctx); } else { parameters.push(ctx[param.name]); } break; case sardines_core_1.Http.ServiceInputParamPosition.session: if (param.name === undefined || param.name === '') { parameters.push(ctx.session); } else if (ctx.session && typeof ctx.session === 'object') { parameters.push(ctx.session[param.name]); } else { parameters.push(null); } break; case sardines_core_1.Http.ServiceInputParamPosition.body: if (param.name === undefined || param.name === '') { parameters.push(ctx.request.body); } else { parameters.push(ctx.request.body[param.name]); } break; case sardines_core_1.Http.ServiceInputParamPosition.files: if (param.name === undefined || param.name === '') { parameters.push(ctx.request.files); } else { parameters.push(ctx.request.files[param.name]); } break; case sardines_core_1.Http.ServiceInputParamPosition.header: if (param.name === undefined || param.name === '') { parameters.push(ctx.request.header); } else { parameters.push(ctx.request.header[param.name]); } break; case sardines_core_1.Http.ServiceInputParamPosition.query: if (param.name === undefined || param.name === '') { parameters.push(ctx.request.query); } else { parameters.push(ctx.request.query[param.name]); } break; case sardines_core_1.Http.ServiceInputParamPosition.cookies: if (param.name === undefined || param.name === '') { parameters.push(ctx.cookies); } else { parameters.push(ctx.cookies.get(param.name)); } break; default: reject("Unsupported parameter position: " + param.position); break; } } else { reject('Parameter definition format error'); } }); } resolve(parameters); }); }; var HttpServiceProvider = (function (_super) { __extends(HttpServiceProvider, _super); function HttpServiceProvider(serverSettings) { return _super.call(this, serverSettings) || this; } HttpServiceProvider.prototype.registerService = function (originalServiceSettings, handler, additionalSettings) { var _this = this; if (handler === void 0) { handler = null; } if (additionalSettings === void 0) { additionalSettings = null; } var application = originalServiceSettings.application || ''; if (!application) { throw sardines_core_1.utils.unifyErrMesg('invalid service settings', 'provider', 'register service'); } var unifiedServiceSettings = null; if ('path' in originalServiceSettings) { unifiedServiceSettings = unifyHttpServiceSettings(originalServiceSettings, this.serverSettings); } else { unifiedServiceSettings = unifyServiceSettings(application, originalServiceSettings, this.serverSettings, additionalSettings, handler); } if (!unifiedServiceSettings || typeof unifiedServiceSettings === 'string') { return Promise.reject(unifiedServiceSettings); } var serviceSettings = unifiedServiceSettings; var processService = function (serviceHandler, ctx, next) { return __awaiter(_this, void 0, void 0, function () { var _i, _a, stage, _b, middlewareHandler, postProcessesHandler, err_1, error; return __generator(this, function (_c) { switch (_c.label) { case 0: _i = 0, _a = ['service custom middlewares', 'service handler', 'service custom post proprecesses']; _c.label = 1; case 1: if (!(_i < _a.length)) return [3, 18]; stage = _a[_i]; _c.label = 2; case 2: _c.trys.push([2, 13, , 17]); _b = stage; switch (_b) { case 'service custom middlewares': return [3, 3]; case 'service handler': return [3, 6]; case 'service custom post proprecesses': return [3, 8]; } return [3, 11]; case 3: middlewareHandler = sardines_core_1.utils.chainFunctions(serviceSettings.middlewares, ctx); if (!middlewareHandler) return [3, 5]; return [4, middlewareHandler()]; case 4: _c.sent(); _c.label = 5; case 5: return [3, 12]; case 6: return [4, serviceHandler()]; case 7: _c.sent(); return [3, 12]; case 8: postProcessesHandler = sardines_core_1.utils.chainFunctions(serviceSettings.postProcesses, ctx); if (!postProcessesHandler) return [3, 10]; return [4, postProcessesHandler()]; case 9: _c.sent(); _c.label = 10; case 10: return [3, 12]; case 11: return [3, 12]; case 12: return [3, 17]; case 13: err_1 = _c.sent(); sardines_core_1.utils.inspectedDebugLog(this.logMesgHeader + " Error when executing <" + stage + "> for service [" + serviceSettings.summary + "]", err_1); error = sardines_core_1.utils.unifyErrMesg(err_1, 'service provider', stage); if (!(typeof this.serverSettings.catcher === 'function')) return [3, 15]; return [4, this.serverSettings.catcher(error, ctx)]; case 14: _c.sent(); return [3, 16]; case 15: throw error; case 16: return [3, 17]; case 17: _i++; return [3, 1]; case 18: return [4, next()]; case 19: _c.sent(); return [2]; } }); }); }; var sendStaticFile = function (filePath, ctx) { return __awaiter(_this, void 0, void 0, function () { var done, err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: sardines_core_1.utils.debugLog(this.logMesgHeader + " going to send static file: " + filePath); done = null; _a.label = 1; case 1: _a.trys.push([1, 3, 4, 5]); return [4, KoaSend(ctx, filePath, { root: serviceSettings.response.path })]; case 2: done = _a.sent(); return [3, 5]; case 3: err_2 = _a.sent(); if (err_2.status !== 404) { sardines_core_1.utils.inspectedDebugLog(this.logMesgHeader + " Error when sending static file <" + filePath + ">", err_2); } return [3, 5]; case 4: if (done) { sardines_core_1.utils.debugLog(this.logMesgHeader + " sent static file <" + filePath + "> with return code: " + done); } return [7]; case 5: return [2]; } }); }); }; var sendText = function (ctx) { return __awaiter(_this, void 0, void 0, function () { var _a, rendered, _i, _b, pair, match, _c; return __generator(this, function (_d) { switch (_d.label) { case 0: ctx.set('content-type', 'text/html'); if (!(typeof serviceSettings.response.path === 'string')) return [3, 2]; _a = ctx; return [4, readFile(serviceSettings.response.path)]; case 1: _a.body = _d.sent(); return [3, 8]; case 2: if (!(Array.isArray(serviceSettings.response.path) && serviceSettings.response.path.length > 0)) return [3, 8]; rendered = false; _i = 0, _b = serviceSettings.response.path; _d.label = 3; case 3: if (!(_i < _b.length)) return [3, 7]; pair = _b[_i]; if (!(typeof pair.selector === 'function' && typeof pair.path === 'string')) return [3, 6]; return [4, pair.selector(ctx)]; case 4: match = _d.sent(); if (!match) return [3, 6]; rendered = true; _c = ctx; return [4, readFile(pair.path)]; case 5: _c.body = _d.sent(); return [3, 7]; case 6: _i++; return [3, 3]; case 7: if (!rendered) { } _d.label = 8; case 8: return [2]; } }); }); }; var execCustomService = function (ctx) { return __awaiter(_this, void 0, void 0, function () { var params, res; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, extractParams(ctx, serviceSettings.inputParameters)]; case 1: params = _a.sent(); sardines_core_1.utils.inspectedDebugLog(this.logMesgHeader + " extracted input from invocation", params); return [4, serviceSettings.handler.apply(serviceSettings, params)]; case 2: res = _a.sent(); switch (serviceSettings.response.type) { case sardines_core_1.Http.ServiceResponseType.text: case sardines_core_1.Http.ServiceResponseType.string: ctx.body = res; break; case sardines_core_1.Http.ServiceResponseType.json: default: if (typeof res !== 'object' || res === null) res = { res: res }; ctx.body = res; break; } return [2]; } }); }); }; var self = this; return new Promise(function (resolve, reject) { self.init().then(function () { try { switch (serviceSettings.response.type) { case sardines_core_1.Http.ServiceResponseType.static: case sardines_core_1.Http.ServiceResponseType.file: self.router[serviceSettings.method](serviceSettings.path, function (ctx, next) { return __awaiter(_this, void 0, void 0, function () { var filePath; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: filePath = (serviceSettings.path.length > 2) ? ctx.path.substr(serviceSettings.path.length - 2) : ctx.path; return [4, processService(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, sendStaticFile(filePath, ctx)]; case 1: return [2, _a.sent()]; } }); }); }, ctx, next)]; case 1: _a.sent(); return [2]; } }); }); }); break; case sardines_core_1.Http.ServiceResponseType.html: case sardines_core_1.Http.ServiceResponseType.render: self.router[serviceSettings.method](serviceSettings.path, function (ctx, next) { return __awaiter(_this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, processService(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, sendText(ctx)]; case 1: return [2, _a.sent()]; } }); }); }, ctx, next)]; case 1: _a.sent(); return [2]; } }); }); }); break; case sardines_core_1.Http.ServiceResponseType.handler: self.router[serviceSettings.method](serviceSettings.path, function (ctx, next) { return __awaiter(_this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, processService(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, serviceSettings.handler(ctx)]; case 1: return [2, _a.sent()]; } }); }); }, ctx, next)]; case 1: _a.sent(); return [2]; } }); }); }); break; case sardines_core_1.Http.ServiceResponseType.json: case sardines_core_1.Http.ServiceResponseType.string: case sardines_core_1.Http.ServiceResponseType.text: default: self.router[serviceSettings.method](serviceSettings.path, function (ctx, next) { return __awaiter(_this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, processService(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { switch (_a.label) { case 0: return [4, execCustomService(ctx)]; case 1: return [2, _a.sent()]; } }); }); }, ctx, next)]; case 1: _a.sent(); return [2]; } }); }); }); break; } sardines_core_1.utils.debugLog(self.logMesgHeader + " successfully registered service [" + serviceSettings.summary + "] on path [" + serviceSettings.path + "]"); resolve(serviceSettings); } catch (err) { sardines_core_1.utils.inspectedDebugLog(self.logMesgHeader + " failed to register service [" + serviceSettings.summary + "] on path [" + serviceSettings.path + "]", err); reject(err); } }); }); }; HttpServiceProvider.prototype.removeService = function (serviceSettings) { return __awaiter(this, void 0, void 0, function () { var i, service; return __generator(this, function (_a) { if (!serviceSettings || !serviceSettings.path || !serviceSettings.method) { throw sardines_core_1.utils.unifyErrMesg("illegal service setting", 'sardines-service-provider-http', 'remove service'); } if (!this.router || !this.router.stack || !this.router.stack.length) { throw sardines_core_1.utils.unifyErrMesg("service provider not ready", 'sardines-service-provider-http', 'remove service'); } for (i = this.router.stack.length; i >= 0; i--) { service = this.router.stack[i]; if (!service) continue; if (!service || !service.path || !service.methods || !service.methods.length) continue; if (service.path === serviceSettings.path && service.methods.indexOf(serviceSettings.method.toUpperCase()) >= 0) { this.router.stack.splice(i, 1); return [2, true]; } } return [2, false]; }); }); }; return HttpServiceProvider; }(Server.HttpServiceProviderServer)); exports.default = HttpServiceProvider; __exportStar(require("./server"), exports);