UNPKG

@kenote/api-proxy

Version:
197 lines (196 loc) 11.3 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()); }); }; 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 }; } }; var __read = (this && this.__read) || function (o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.toResponseResult = exports.getNodeResponse = exports.getNodeEntrance = void 0; var path_1 = require("path"); var http_errors_1 = __importDefault(require("http-errors")); var js_yaml_1 = __importDefault(require("js-yaml")); var rule_judgment_1 = __importDefault(require("rule-judgment")); var parse_string_1 = require("parse-string"); var config_1 = require("@kenote/config"); var lodash_1 = require("lodash"); var utils_1 = require("./utils"); var api_proxy_1 = require("./api-proxy"); var http_1 = require("./http"); var socket_1 = require("./socket"); function getNodeEntrance(options) { var _this = this; return function (ctx, pathname) { return __awaiter(_this, void 0, void 0, function () { var channel, pathLabel, sandbox, channelPath, allEntrance, entrance, setting, serviceModules, whitelist, isAuth, body, payload; var _a; return __generator(this, function (_b) { switch (_b.label) { case 0: channel = options.channel, pathLabel = options.pathLabel, sandbox = options.sandbox; if (!(ctx === null || ctx === void 0 ? void 0 : ctx.channel) || !(ctx === null || ctx === void 0 ? void 0 : ctx.pathLabel)) { throw (0, http_errors_1.default)(500, '缺少频道和路径', { code: 1000 }); } channelPath = (0, path_1.resolve)(process.cwd(), pathname, channel); allEntrance = (0, config_1.loadConfig)([pathname, channel, 'wss'].join('/'), { type: 'array' }); entrance = allEntrance === null || allEntrance === void 0 ? void 0 : allEntrance.find(function (v) { return v.name === pathLabel; }); if (!entrance) { throw (0, http_errors_1.default)(500, '当前访问的接口不存在', { code: 1000 }); } setting = (0, config_1.loadConfig)([pathname, channel, 'setting'].join('/'), { mode: 'merge' }); return [4, (0, utils_1.getServiceModules)({ cwd: (0, path_1.resolve)(channelPath, 'js'), sandbox: sandbox, alias: setting === null || setting === void 0 ? void 0 : setting.jsAlias })]; case 1: serviceModules = _b.sent(); whitelist = (0, lodash_1.uniq)((0, lodash_1.compact)((0, lodash_1.concat)(setting === null || setting === void 0 ? void 0 : setting.whitelist, entrance === null || entrance === void 0 ? void 0 : entrance.whitelist))); if (whitelist.length > 0 && !whitelist.find(function (v) { return new RegExp(v).test(ctx.clientIP); })) { throw (0, http_errors_1.default)(500, '没有访问该页面的权限 [whitelist]', { code: 1000 }); } if (entrance.filterAuth) { isAuth = (0, rule_judgment_1.default)(entrance.filterAuth)(ctx.auth); if (!isAuth) { throw (0, http_errors_1.default)(500, '没有访问该页面的权限 [Unauthorized]', { code: 1000 }); } } body = (_a = ctx === null || ctx === void 0 ? void 0 : ctx.body) !== null && _a !== void 0 ? _a : {}; payload = entrance.payload ? (0, parse_string_1.filterData)(entrance.payload, serviceModules)(body) : body; payload = (0, api_proxy_1.parseProps)(entrance.props)(payload); serviceModules.payload = payload; return [2, { serviceModules: serviceModules, payload: payload, entrance: entrance, setting: setting }]; } }); }); }; } exports.getNodeEntrance = getNodeEntrance; function getNodeResponse(entrance, payload) { var _this = this; return function (options) { return __awaiter(_this, void 0, void 0, function () { var serviceModules, logger, setting, result, type, _a, name_1, args, httpProxy, ret, _b, code, _c, msgtype, requestType, serverTag, tag, tcpSocket, server; var _d, _e, _f, _g; return __generator(this, function (_h) { switch (_h.label) { case 0: serviceModules = options.serviceModules, logger = options.logger, setting = options.setting; result = null; type = 'application/octet-stream'; if (!(entrance === null || entrance === void 0 ? void 0 : entrance.service)) return [3, 2]; _a = entrance.service, name_1 = _a.name, args = _a.args; return [4, (0, utils_1.runService)(name_1, args)(serviceModules)]; case 1: result = _h.sent(); return [3, 6]; case 2: if (!(entrance === null || entrance === void 0 ? void 0 : entrance.httpProxy)) return [3, 4]; httpProxy = entrance.httpProxy; if (httpProxy.method.toUpperCase() === 'GET') { httpProxy.params = (0, lodash_1.merge)(httpProxy.params, payload); } else { httpProxy.body = (0, lodash_1.merge)(httpProxy.body, payload); } return [4, (0, http_1.shellAsCurl)(httpProxy)]; case 3: ret = _h.sent(); _b = __read((_e = (_d = ret.status) === null || _d === void 0 ? void 0 : _d.split(/\s+/)) !== null && _e !== void 0 ? _e : [], 2), code = _b[1]; if (code != '200') { throw (0, http_errors_1.default)(500, ['HttpProxy:', (_f = ret.status) === null || _f === void 0 ? void 0 : _f.replace('404 OK', '404 Not Found')].join(''), { code: 1000 }); } result = ret.body; type = (0, utils_1.getHeader)('content-type')((_g = ret.headers) !== null && _g !== void 0 ? _g : []); return [3, 6]; case 4: if (!(entrance === null || entrance === void 0 ? void 0 : entrance.socketProxy)) return [3, 6]; _c = entrance.socketProxy, msgtype = _c.msgtype, requestType = _c.requestType, serverTag = _c.serverTag; tag = void 0; tcpSocket = { port: 8080 }; server = []; if ((0, lodash_1.isPlainObject)(serverTag)) { tcpSocket = serverTag; } else if ((0, lodash_1.isString)(serverTag)) { tag = serverTag; } if (setting) { tcpSocket = (0, lodash_1.merge)(tcpSocket, setting === null || setting === void 0 ? void 0 : setting.tcpSocket); } tcpSocket.logger = logger; return [4, (0, socket_1.socketRequest)(msgtype, payload, requestType)({ tcpSocket: tcpSocket, server: server, tag: tag })]; case 5: result = _h.sent(); _h.label = 6; case 6: result = (0, utils_1.parsePlainObject)(result, entrance === null || entrance === void 0 ? void 0 : entrance.parse)(serviceModules); return [2, [type, result]]; } }); }); }; } exports.getNodeResponse = getNodeResponse; function toResponseResult(path, data, type) { var result = { timestamp: Date.now(), path: path }; if ((0, lodash_1.isError)(data)) { result.error = data.message; } else if ((0, lodash_1.isBuffer)(data)) { result.data = (0, config_1.isJson)(data.toString()) || (0, config_1.isYaml)(data.toString()) ? js_yaml_1.default.load(data) : data.toString(); } else { result.data = data; } return JSON.stringify(result); } exports.toResponseResult = toResponseResult;