UNPKG

30.7 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10var __generator = (this && this.__generator) || function (thisArg, body) {
11 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
12 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
13 function verb(n) { return function (v) { return step([n, v]); }; }
14 function step(op) {
15 if (f) throw new TypeError("Generator is already executing.");
16 while (_) try {
17 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;
18 if (y = 0, t) op = [op[0] & 2, t.value];
19 switch (op[0]) {
20 case 0: case 1: t = op; break;
21 case 4: _.label++; return { value: op[1], done: false };
22 case 5: _.label++; y = op[1]; op = [0]; continue;
23 case 7: op = _.ops.pop(); _.trys.pop(); continue;
24 default:
25 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
26 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
27 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
28 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
29 if (t[2]) _.ops.pop();
30 _.trys.pop(); continue;
31 }
32 op = body.call(thisArg, _);
33 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
34 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
35 }
36};
37Object.defineProperty(exports, "__esModule", { value: true });
38// 根据架构设计约定自动识别各种运行环境
39if (process.env['NODE_ENV']) {
40 global['__env__'] = process.env['NODE_ENV'];
41}
42else {
43 if (process.argv.length >= 3 && process.argv[2] == 'https') {
44 // 预发环境配置
45 global['__env__'] = 'pre';
46 }
47 else if (process.argv.length >= 3 && process.argv[2] == 'http') {
48 // 日常环境配置
49 global['__env__'] = 'daily';
50 }
51 else {
52 // 本地环境配置
53 global['__env__'] = 'local';
54 }
55}
56if (global['__env__'] != 'local') {
57 require('source-map-support').install();
58}
59require('tsconfig-paths').register();
60var express = require('express');
61var app = express();
62var _ = require('lodash');
63var path = require('path');
64var http = require('http');
65var https = require('https');
66var fs = require('fs');
67var init_1 = require("./init");
68// 端口号启动参数配置
69var PORT = parseInt(process.argv[2]);
70if (!PORT) {
71 PORT = 8888;
72}
73// 设置静态资源路径(必须要使用绝对路径)
74app.use(express.static(path.join(init_1.get_root_path_prefix(), './static')));
75// 引入json解析中间件
76var bodyParser = require('body-parser');
77app.use(function (req, res, next) {
78 var rawBody = [];
79 var size = 0;
80 req.on('data', function (data) {
81 rawBody.push(data);
82 size += data.length;
83 });
84 req.on('end', function () {
85 // 获取原始的content-type对应的body内容自行解析处理,解决本地环境和线上环境不兼容问题。
86 req.rawBody = Buffer.concat(rawBody, size).toString();
87 });
88 next();
89});
90// 添加json解析
91app.use(bodyParser.json());
92app.use(bodyParser.urlencoded({ extended: false }));
93// 允许所有的请求形式
94app.use(function (req, res, next) {
95 if (req.headers.origin) {
96 // 获取源站动态允许请求跨域 (FIXME 需要进行安全限制对来源服务器网址合法性进行安全限制,本地开发调试全部放开请求)
97 res.header("Access-Control-Allow-Origin", req.headers.origin);
98 }
99 // res.header("Access-Control-Allow-Origin", "*")
100 res.header("Access-Control-Allow-Credentials", "true");
101 res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
102 res.header('Access-Control-Allow-Methods', 'POST, OPTIONS');
103 next();
104});
105// 本地调试使用路由重定向映射功能模拟
106var routes = require(path.join(init_1.get_root_path_prefix(), './app/entries/route.map')).default;
107var _loop_1 = function (k) {
108 app.all(k, function (req, res) {
109 return __awaiter(this, void 0, void 0, function () {
110 return __generator(this, function (_a) {
111 req.headers.__api__ = routes[k].path;
112 callback(req, res);
113 return [2 /*return*/];
114 });
115 });
116 });
117};
118for (var k in routes) {
119 _loop_1(k);
120}
121// TODO SLS日志机制云端对接、监控机制的业务对接、性能测试的对接、ACM配置机制的对接、报错机制信息的正确解析处理、
122// TODO COOKIE解析、BUC登录验证、 会议室信息的JAVA接口联调、梅丽莎多语言对接、ACM的配置发布
123// TODO 错误页处理、SESSION模拟基于TableStore的实现、REST的实现、更多PAAS中间件根据业务需要对接集成进来、实际业务问题更多的优化扩展。。。
124// 匹配不包含.的所有路由进行处理,否则表示文件静态资源需要单独处理。(API网关不返回任何静态资源,静态资源需要全部上传到CDN上,API网关只处理一个网站图标请求)
125app.all(/^((?!\.).)*$/, callback);
126// TODO 通过请求的域名和入口文件的位置,自动区分:本地、日常、预发、线上,四种环境。(灰度通过线上版本位置自动区分)
127// 加载配置文件信息。。。比较特殊需要在每次请求的时候单独处理。
128// 日常与预发在一台机器上需要分别启动两个独立nodejs进程进行处理,确保二者内部运行太壮数据的隔离性。
129// nodejs服务支持证书配置问题,使用正式的域名证书进行绑定配置,测试的时候本地配置域名链接确保正常。
130if (process.argv[2] == 'https') {
131 // 预发绑定HTTPS服务(对应AONE的日常机器)
132 var privateKey = fs.readFileSync(path.join(init_1.get_root_path_prefix(), './secrete/private.pem'), 'utf8');
133 var certificate = fs.readFileSync(path.join(init_1.get_root_path_prefix(), './secrete/public.crt'), 'utf8');
134 var credentials = { key: privateKey, cert: certificate };
135 var httpsServer = https.createServer(credentials, app);
136 httpsServer.listen(443, function () {
137 console.log('fc pre-release-test app listening on port 443!');
138 });
139}
140else if (process.argv[2] == 'http') {
141 // 日常绑定HTTP服务(对应AONE的日常机器,一台机器同时配置HTTP日常和HTTPS预发)
142 var httpServer = http.createServer(app);
143 httpServer.listen(80, function () {
144 console.log('fc test app listening on port 80!');
145 });
146}
147else {
148 // 本地开发环境HTTP协议绑定指定的端口号
149 var httpServer = http.createServer(app);
150 httpServer.listen(PORT, function () {
151 console.log("fc test app listening on port " + PORT + ", visit http://127.0.0.1:" + PORT);
152 });
153}
154function callback(req, res) {
155 return __awaiter(this, void 0, void 0, function () {
156 var param, __api__, __url__, __header__, out, err_1;
157 return __generator(this, function (_a) {
158 switch (_a.label) {
159 case 0:
160 param = req.query || {};
161 __api__ = req.headers.__api__ ? req.headers.__api__ : req.path;
162 __url__ = req.protocol + '://' + req.get('host') + req.originalUrl;
163 _a.label = 1;
164 case 1:
165 _a.trys.push([1, 3, , 5]);
166 // 请求参数的自动格式化处理兼容get和post协议方便开发调试
167 switch (req.method) {
168 case 'GET':
169 break;
170 case 'POST':
171 param = xassign(param, init_1.parse_post_param(req.headers, req.rawBody));
172 break;
173 case 'OPTIONS':
174 // 仅仅支持本地开发跨域调试,线上需要禁止此方法的调用应该同域请求处理。
175 res.sendStatus(200);
176 return [2 /*return*/];
177 default:
178 // 400 Bad Request 客户端请求的语法错误,服务器无法理解
179 res.sendStatus(400);
180 return [2 /*return*/];
181 }
182 __header__ = req.headers;
183 param = xassign(param, { __api__: __api__, __url__: __url__, __header__: __header__ });
184 // 解析请求中的cookies数据并转换为JSON对象存储到全局变量中便于后续应用xcookie接口使用
185 global['__request_cookies__'] = require('cookie').parse(_.get(req.headers, 'cookie', ''));
186 // 获取use-agent请求头部信息
187 global['__user_agent__'] = req['headers'] ? (req['headers']['user-agent'] ? req['headers']['user-agent'] : '') : '';
188 // 取到客户端的IP地址信息
189 global['__client_ip__'] = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
190 return [4 /*yield*/, init_1.request_process(__api__, param)
191 // 处理response的cookies设置
192 ];
193 case 2:
194 out = _a.sent();
195 // 处理response的cookies设置
196 if (!_.isEmpty(global['__respond_cookies__'])) {
197 res.setHeader('Set-Cookie', _.values(global['__respond_cookies__']));
198 }
199 if (global['__redirect_url__']) {
200 res.redirect(302, global['__redirect_url__']);
201 global['__redirect_url__'] = undefined;
202 return [2 /*return*/];
203 }
204 res.send(out);
205 return [3 /*break*/, 5];
206 case 3:
207 err_1 = _a.sent();
208 // 通知框架自身实现逻辑的意外报错(框架自身不论何种情况都应该正常工作,一旦出现此问题大多数情况是框架自身问题或者流量引发的运维问题)
209 return [4 /*yield*/, xwarn({
210 __api__: __api__, __url__: __url__, param: param, message: err_1.message, stack: xstack(err_1)
211 })
212 // 500 Internal Server Error 服务器内部错误,无法完成请求
213 ];
214 case 4:
215 // 通知框架自身实现逻辑的意外报错(框架自身不论何种情况都应该正常工作,一旦出现此问题大多数情况是框架自身问题或者流量引发的运维问题)
216 _a.sent();
217 // 500 Internal Server Error 服务器内部错误,无法完成请求
218 res.sendStatus(500);
219 return [3 /*break*/, 5];
220 case 5: return [2 /*return*/];
221 }
222 });
223 });
224}
225//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHFCQUFxQjtBQUNyQixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLEVBQUU7SUFDekIsTUFBTSxDQUFDLFNBQVMsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLENBQUE7Q0FDOUM7S0FBTTtJQUNILElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxFQUFFO1FBQ3hELFNBQVM7UUFDVCxNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsS0FBSyxDQUFBO0tBQzVCO1NBQU0sSUFBSSxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLElBQUksT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxNQUFNLEVBQUU7UUFDOUQsU0FBUztRQUNULE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxPQUFPLENBQUE7S0FDOUI7U0FDSTtRQUNELFNBQVM7UUFDVCxNQUFNLENBQUMsU0FBUyxDQUFDLEdBQUcsT0FBTyxDQUFBO0tBQzlCO0NBQ0o7QUFDRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsSUFBSSxPQUFPLEVBQUU7SUFDOUIsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQUMsT0FBTyxFQUFFLENBQUE7Q0FDMUM7QUFDRCxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtBQUNwQyxJQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUE7QUFDbEMsSUFBTSxHQUFHLEdBQUcsT0FBTyxFQUFFLENBQUE7QUFDckIsSUFBTSxDQUFDLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FB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WUFBWSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFBO3FCQUN2RTtvQkFFRCxJQUFJLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFO3dCQUM1QixHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsRUFBRSxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFBO3dCQUM3QyxNQUFNLENBQUMsa0JBQWtCLENBQUMsR0FBRyxTQUFTLENBQUE7d0JBQ3RDLHNCQUFNO3FCQUNUO29CQUNELEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7Ozs7b0JBRWIsb0VBQW9FO29CQUNwRSxxQkFBTSxLQUFLLENBQUM7NEJBQ1IsT0FBTyxTQUFBLEVBQUUsT0FBTyxTQUFBLEVBQUUsS0FBSyxPQUFBLEVBQUUsT0FBTyxFQUFFLEtBQUcsQ0FBQyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFHLENBQUM7eUJBQ3BFLENBQUM7d0JBQ0YsMkNBQTJDO3NCQUR6Qzs7b0JBSEYsb0VBQW9FO29CQUNwRSxTQUVFLENBQUE7b0JBQ0YsMkNBQTJDO29CQUMzQyxHQUFHLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFBOzs7Ozs7Q0FFMUIiLCJzb3VyY2VzQ29udGVudCI6WyIvLyDmoLnmja7mnrbmnoTorr7orqHnuqblrproh6rliqjor4bliKvlkITnp43ov5DooYznjq/looNcbmlmIChwcm9jZXNzLmVudlsnTk9ERV9FTlYnXSkge1xuICAgIGdsb2JhbFsnX19lbnZfXyddID0gcHJvY2Vzcy5lbnZbJ05PREVfRU5WJ11cbn0gZWxzZSB7XG4gICAgaWYgKHByb2Nlc3MuYXJndi5sZW5ndGggPj0gMyAmJiBwcm9jZXNzLmFyZ3ZbMl0gPT0gJ2h0dHBzJykge1xuICAgICAgICAvLyDpooTlj5Hnjq/looPphY3nva5cbiAgICAgICAgZ2xvYmFsWydfX2Vudl9fJ10gPSAncHJlJ1xuICAgIH0gZWxzZSBpZiAocHJvY2Vzcy5hcmd2Lmxlbmd0aCA+PSAzICYmIHByb2Nlc3MuYXJndlsyXSA9PSAnaHR0cCcpIHtcbiAgICAgICAgLy8g5pel5bi4546v5aKD6YWN572uXG4gICAgICAgIGdsb2JhbFsnX19lbnZfXyddID0gJ2RhaWx5J1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgLy8g5pys5Zyw546v5aKD6YWN572uXG4gICAgICAgIGdsb2JhbFsnX19lbnZfXyddID0gJ2xvY2FsJ1xuICAgIH1cbn1cbmlmIChnbG9iYWxbJ19fZW52X18nXSAhPSAnbG9jYWwnKSB7XG4gICAgcmVxdWlyZSgnc291cmNlLW1hcC1zdXBwb3J0JykuaW5zdGFsbCgpXG59XG5yZXF1aXJlKCd0c2NvbmZpZy1wYXRocycpLnJlZ2lzdGVyKClcbmNvbnN0IGV4cHJlc3MgPSByZXF1aXJlKCdleHByZXNzJylcbmNvbnN0IGFwcCA9IGV4cHJlc3MoKVxuY29uc3QgXyA9IHJlcXVpcmUoJ2xvZGFzaCcpXG5jb25zdCBwYXRoID0gcmVxdWlyZSgncGF0aCcpXG5jb25zdCBodHRwID0gcmVxdWlyZSgnaHR0cCcpXG5jb25zdCBodHRwcyA9IHJlcXVpcmUoJ2h0dHBzJylcbmNvbnN0IGZzID0gcmVxdWlyZSgnZnMnKVxuaW1wb3J0IHtnZXRfcm9vdF9wYXRoX3ByZWZpeCwgcmVxdWVzdF9wcm9jZXNzLCBwYXJzZV9wb3N0X3BhcmFtfSBmcm9tICcuL2luaXQnXG5cbi8vIOerr+WPo+WPt+WQr+WKqOWPguaVsOmFjee9rlxubGV0IFBPUlQ6IGFueSA9IHBhcnNlSW50KHByb2Nlc3MuYXJndlsyXSlcbmlmICghUE9SVCkge1xuICAgIFBPUlQgPSA4ODg4XG59XG5cbi8vIOiuvue9rumdmeaAgei1hOa6kOi3r+W+hO+8iOW/hemhu+imgeS9v+eUqOe7neWvuei3r+W+hO+8iVxuYXBwLnVzZShleHByZXNzLnN0YXRpYyhwYXRoLmpvaW4oZ2V0X3Jvb3RfcGF0aF9wcmVmaXgoKSwgJy4vc3RhdGljJykpKVxuXG4vLyDlvJXlhaVqc29u6Kej5p6Q5Lit6Ze05Lu2XG5jb25zdCBib2R5UGFyc2VyID0gcmVxdWlyZSgnYm9keS1wYXJzZXInKVxuYXBwLnVzZShmdW5jdGlvbiAocmVxLCByZXMsIG5leHQpIHtcbiAgICB2YXIgcmF3Qm9keSA9IFtdXG4gICAgdmFyIHNpemUgPSAwXG4gICAgcmVxLm9uKCdkYXRhJywgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgcmF3Qm9keS5wdXNoKGRhdGEpXG4gICAgICAgIHNpemUgKz0gZGF0YS5sZW5ndGhcbiAgICB9KVxuICAgIHJlcS5vbignZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyDojrflj5bljp/lp4vnmoRjb250ZW50LXR5cGXlr7nlupTnmoRib2R55YaF5a656Ieq6KGM6Kej5p6Q5aSE55CG77yM6Kej5Yaz5pys5Zyw546v5aKD5ZKM57q/5LiK546v5aKD5LiN5YW85a656Zeu6aKY44CCXG4gICAgICAgIHJlcS5yYXdCb2R5ID0gQnVmZmVyLmNvbmNhdChyYXdCb2R5LCBzaXplKS50b1N0cmluZygpXG4gICAgfSlcbiAgICBuZXh0KClcbn0pXG4vLyDmt7vliqBqc29u6Kej5p6QXG5hcHAudXNlKGJvZHlQYXJzZXIuanNvbigpKVxuYXBwLnVzZShib2R5UGFyc2VyLnVybGVuY29kZWQoe2V4dGVuZGVkOiBmYWxzZX0pKVxuLy8g5YWB6K645omA5pyJ55qE6K+35rGC5b2i5byPXG5hcHAudXNlKGZ1bmN0aW9uIChyZXEsIHJlcywgbmV4dCkge1xuICAgIGlmIChyZXEuaGVhZGVycy5vcmlnaW4pIHtcbiAgICAgICAgLy8g6I635Y+W5rqQ56uZ5Yqo5oCB5YWB6K646K+35rGC6Leo5Z+fIChGSVhNRSDpnIDopoHov5vooYzlronlhajpmZDliLblr7nmnaXmupDmnI3liqHlmajnvZHlnYDlkIjms5XmgKfov5vooYzlronlhajpmZDliLbvvIzmnKzlnLDlvIDlj5HosIPor5Xlhajpg6jmlL7lvIDor7fmsYIpXG4gICAgICAgIHJlcy5oZWFkZXIoXCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW5cIiwgcmVxLmhlYWRlcnMub3JpZ2luKTtcbiAgICB9XG4gICAgLy8gcmVzLmhlYWRlcihcIkFjY2Vzcy1Db250cm9sLUFsbG93LU9yaWdpblwiLCBcIipcIilcbiAgICByZXMuaGVhZGVyKFwiQWNjZXNzLUNvbnRyb2wtQWxsb3ctQ3JlZGVudGlhbHNcIiwgXCJ0cnVlXCIpXG4gICAgcmVzLmhlYWRlcihcIkFjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnNcIiwgXCJPcmlnaW4sIFgtUmVxdWVzdGVkLVdpdGgsIENvbnRlbnQtVHlwZSwgQWNjZXB0XCIpXG4gICAgcmVzLmhlYWRlcignQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcycsICdQT1NULCBPUFRJT05TJylcbiAgICBuZXh0KClcbn0pXG5cbi8vIOacrOWcsOiwg+ivleS9v+eUqOi3r+eUsemHjeWumuWQkeaYoOWwhOWKn+iDveaooeaLn1xuY29uc3Qgcm91dGVzID0gcmVxdWlyZShwYXRoLmpvaW4oZ2V0X3Jvb3RfcGF0aF9wcmVmaXgoKSwgJy4vYXBwL2VudHJpZXMvcm91dGUubWFwJykpLmRlZmF1bHRcbmZvciAobGV0IGsgaW4gcm91dGVzKSB7XG4gICAgYXBwLmFsbChrLCBhc3luYyBmdW5jdGlvbiAocmVxLCByZXMpIHtcbiAgICAgICAgcmVxLmhlYWRlcnMuX19hcGlfXyA9IHJvdXRlc1trXS5wYXRoXG4gICAgICAgIGNhbGxiYWNrKHJlcSwgcmVzKVxuICAgIH0pXG59XG5cbi8vIFRPRE8gU0xT5pel5b+X5py65Yi25LqR56uv5a+55o6l44CB55uR5o6n5py65Yi255qE5Lia5Yqh5a+55o6l44CB5oCn6IO95rWL6K+V55qE5a+55o6l44CBQUNN6YWN572u5py65Yi255qE5a+55o6l44CB5oql6ZSZ5py65Yi25L+h5oGv55qE5q2j56Gu6Kej5p6Q5aSE55CG44CBXG4vLyBUT0RPIENPT0tJReino+aekOOAgUJVQ+eZu+W9lemqjOivgeOAgSAgIOS8muiuruWupOS/oeaBr+eahEpBVkHmjqXlj6PogZTosIPjgIHmooXkuL3ojo7lpJror63oqIDlr7nmjqXjgIFBQ03nmoTphY3nva7lj5HluINcbi8vIFRPRE8g6ZSZ6K+v6aG15aSE55CG44CBU0VTU0lPTuaooeaLn+WfuuS6jlRhYmxlU3RvcmXnmoTlrp7njrDjgIFSRVNU55qE5a6e546w44CB5pu05aSaUEFBU+S4remXtOS7tuagueaNruS4muWKoemcgOimgeWvueaOpembhuaIkOi/m+adpeOAgeWunumZheS4muWKoemXrumimOabtOWkmueahOS8mOWMluaJqeWxleOAguOAguOAglxuLy8g5Yy56YWN5LiN5YyF5ZCrLueahOaJgOaciei3r+eUsei/m+ihjOWkhOeQhu+8jOWQpuWImeihqOekuuaWh+S7tumdmeaAgei1hOa6kOmcgOimgeWNleeLrOWkhOeQhuOAgu+8iEFQSee9keWFs+S4jei/lOWbnuS7u+S9lemdmeaAgei1hOa6kO+8jOmdmeaAgei1hOa6kOmcgOimgeWFqOmDqOS4iuS8oOWIsENETuS4iu+8jEFQSee9keWFs+WPquWkhOeQhuS4gOS4que9keermeWbvuagh+ivt+axgu+8iVxuYXBwLmFsbCgvXigoPyFcXC4pLikqJC8sIGNhbGxiYWNrKVxuXG4vLyBUT0RPIOmAmui/h+ivt+axgueahOWfn+WQjeWSjOWFpeWPo+aWh+S7tueahOS9jee9ru+8jOiHquWKqOWMuuWIhu+8muacrOWcsOOAgeaXpeW4uOOAgemihOWPkeOAgee6v+S4iu+8jOWbm+enjeeOr+Wig+OAgu+8iOeBsOW6pumAmui/h+e6v+S4iueJiOacrOS9jee9ruiHquWKqOWMuuWIhu+8iVxuLy8g5Yqg6L296YWN572u5paH5Lu25L+h5oGv44CC44CC44CC5q+U6L6D54m55q6K6ZyA6KaB5Zyo5q+P5qyh6K+35rGC55qE5pe25YCZ5Y2V54us5aSE55CG44CCXG4vLyDml6XluLjkuI7pooTlj5HlnKjkuIDlj7DmnLrlmajkuIrpnIDopoHliIbliKvlkK/liqjkuKTkuKrni6znq4tub2RlanPov5vnqIvov5vooYzlpITnkIbvvIznoa7kv53kuozogIXlhoXpg6jov5DooYzlpKrlo67mlbDmja7nmoTpmpTnprvmgKfjgIJcblxuLy8gbm9kZWpz5pyN5Yqh5pSv5oyB6K+B5Lmm6YWN572u6Zeu6aKY77yM5L2/55So5q2j5byP55qE5Z+f5ZCN6K+B5Lmm6L+b6KGM57uR5a6a6YWN572u77yM5rWL6K+V55qE5pe25YCZ5pys5Zyw6YWN572u5Z+f5ZCN6ZO+5o6l56Gu5L+d5q2j5bi444CCXG5pZiAocHJvY2Vzcy5hcmd2WzJdID09ICdodHRwcycpIHtcbiAgICAvLyDpooTlj5Hnu5HlrppIVFRQU+acjeWKoe+8iOWvueW6lEFPTkXnmoTml6XluLjmnLrlmajvvIlcbiAgICBjb25zdCBwcml2YXRlS2V5ID0gZnMucmVhZEZpbGVTeW5jKFxuICAgICAgICBwYXRoLmpvaW4oZ2V0X3Jvb3RfcGF0aF9wcmVmaXgoKSwgJy4vc2VjcmV0ZS9wcml2YXRlLnBlbScpLCAndXRmOCcpXG4gICAgY29uc3QgY2VydGlmaWNhdGUgPSBmcy5yZWFkRmlsZVN5bmMoXG4gICAgICAgIHBhdGguam9pbihnZXRfcm9vdF9wYXRoX3ByZWZpeCgpLCAnLi9zZWNyZXRlL3B1YmxpYy5jcnQnKSwgJ3V0ZjgnKVxuICAgIGNvbnN0IGNyZWRlbnRpYWxzID0ge2tleTogcHJpdmF0ZUtleSwgY2VydDogY2VydGlmaWNhdGV9XG4gICAgY29uc3QgaHR0cHNTZXJ2ZXIgPSBodHRwcy5jcmVhdGVTZXJ2ZXIoY3JlZGVudGlhbHMsIGFwcClcbiAgICBodHRwc1NlcnZlci5saXN0ZW4oNDQzLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdmYyBwcmUtcmVsZWFzZS10ZXN0IGFwcCBsaXN0ZW5pbmcgb24gcG9ydCA0NDMhJylcbiAgICB9KVxufSBlbHNlIGlmIChwcm9jZXNzLmFyZ3ZbMl0gPT0gJ2h0dHAnKSB7XG4gICAgLy8g5pel5bi457uR5a6aSFRUUOacjeWKoe+8iOWvueW6lEFPTkXnmoTml6XluLjmnLrlmajvvIzkuIDlj7DmnLrlmajlkIzml7bphY3nva5IVFRQ5pel5bi45ZKMSFRUUFPpooTlj5HvvIlcbiAgICBjb25zdCBodHRwU2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoYXBwKVxuICAgIGh0dHBTZXJ2ZXIubGlzdGVuKDgwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdmYyB0ZXN0IGFwcCBsaXN0ZW5pbmcgb24gcG9ydCA4MCEnKVxuICAgIH0pXG59IGVsc2Uge1xuICAgIC8vIOacrOWcsOW8gOWPkeeOr+Wig0hUVFDljY/orq7nu5HlrprmjIflrprnmoTnq6/lj6Plj7dcbiAgICBjb25zdCBodHRwU2VydmVyID0gaHR0cC5jcmVhdGVTZXJ2ZXIoYXBwKVxuICAgIGh0dHBTZXJ2ZXIubGlzdGVuKFBPUlQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgY29uc29sZS5sb2coYGZjIHRlc3QgYXBwIGxpc3RlbmluZyBvbiBwb3J0ICR7UE9SVH0sIHZpc2l0IGh0dHA6Ly8xMjcuMC4wLjE6JHtQT1JUfWApXG4gICAgfSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gY2FsbGJhY2socmVxLCByZXMpIHtcbiAgICBsZXQgcGFyYW0gPSByZXEucXVlcnkgfHwge31cbiAgICAvLyDooaXkuIrmoYbmnrbpooTlrprkuYnnmoTnvLrnnIHlj4LmlbBfX3VybF9fKOWFtuS7luabtOWkmuahhuaetuWPguaVsF9fYXBpX18gX19kZWJ1Z19fIF9fbW9ja19fIFRPRE8gX19wYXJhbV9fIOWcqGdldOS4rWpzb27lrZfnrKbkuLLnmoRiYXNlNjTmoLzlvI8pXG4gICAgbGV0IF9fYXBpX18gPSByZXEuaGVhZGVycy5fX2FwaV9fID8gcmVxLmhlYWRlcnMuX19hcGlfXyA6IHJlcS5wYXRoXG4gICAgbGV0IF9fdXJsX18gPSByZXEucHJvdG9jb2wgKyAnOi8vJyArIHJlcS5nZXQoJ2hvc3QnKSArIHJlcS5vcmlnaW5hbFVybFxuXG4gICAgdHJ5IHtcbiAgICAgICAgLy8g6K+35rGC5Y+C5pWw55qE6Ieq5Yqo5qC85byP5YyW5aSE55CG5YW85a65Z2V05ZKMcG9zdOWNj+iuruaWueS+v+W8gOWPkeiwg+ivlVxuICAgICAgICBzd2l0Y2ggKHJlcS5tZXRob2QpIHtcbiAgICAgICAgICAgIGNhc2UgJ0dFVCc6XG4gICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgIGNhc2UgJ1BPU1QnOlxuICAgICAgICAgICAgICAgIHBhcmFtID0geGFzc2lnbihwYXJhbSwgcGFyc2VfcG9zdF9wYXJhbShyZXEuaGVhZGVycywgcmVxLnJhd0JvZHkpKVxuICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICBjYXNlICdPUFRJT05TJzpcbiAgICAgICAgICAgICAgICAvLyDku4Xku4XmlK/mjIHmnKzlnLDlvIDlj5Hot6jln5/osIPor5XvvIznur/kuIrpnIDopoHnpoHmraLmraTmlrnms5XnmoTosIPnlKjlupTor6XlkIzln5/or7fmsYLlpITnkIbjgIJcbiAgICAgICAgICAgICAgICByZXMuc2VuZFN0YXR1cygyMDApXG4gICAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIC8vIDQwMCAgQmFkIFJlcXVlc3RcdOWuouaIt+err+ivt+axgueahOivreazlemUmeivr++8jOacjeWKoeWZqOaXoOazleeQhuino1xuICAgICAgICAgICAgICAgIHJlcy5zZW5kU3RhdHVzKDQwMClcbiAgICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICAvLyDooaXkuIror7fmsYLnmoRIRUFERVLlj4LmlbDliLDlupTnlKjkuK3ov5vooYzoh6rooYzlpITnkIbkuJrliqHpgLvovpHlrprliLbnmoTor7fmsYLlpLTpg6jkv6Hmga9cbiAgICAgICAgbGV0IF9faGVhZGVyX18gPSByZXEuaGVhZGVyc1xuICAgICAgICBwYXJhbSA9IHhhc3NpZ24ocGFyYW0sIHtfX2FwaV9fLCBfX3VybF9fLCBfX2hlYWRlcl9ffSlcblxuICAgICAgICAvLyDop6PmnpDor7fmsYLkuK3nmoRjb29raWVz5pWw5o2u5bm26L2s5o2i5Li6SlNPTuWvueixoeWtmOWCqOWIsOWFqOWxgOWPmOmHj+S4reS+v+S6juWQjue7reW6lOeUqHhjb29raWXmjqXlj6Pkvb/nlKhcbiAgICAgICAgZ2xvYmFsWydfX3JlcXVlc3RfY29va2llc19fJ10gPSByZXF1aXJlKCdjb29raWUnKS5wYXJzZShfLmdldChyZXEuaGVhZGVycywgJ2Nvb2tpZScsICcnKSlcblxuICAgICAgICAvLyDojrflj5Z1c2UtYWdlbnTor7fmsYLlpLTpg6jkv6Hmga9cbiAgICAgICAgZ2xvYmFsWydfX3VzZXJfYWdlbnRfXyddID0gcmVxWydoZWFkZXJzJ10gPyAocmVxWydoZWFkZXJzJ11bJ3VzZXItYWdlbnQnXSA/IHJlcVsnaGVhZGVycyddWyd1c2VyLWFnZW50J10gOiAnJykgOiAnJ1xuXG4gICAgICAgIC8vIOWPluWIsOWuouaIt+err+eahElQ5Zyw5Z2A5L+h5oGvXG4gICAgICAgIGdsb2JhbFsnX19jbGllbnRfaXBfXyddID0gcmVxLmhlYWRlcnNbJ3gtZm9yd2FyZGVkLWZvciddIHx8IHJlcS5jb25uZWN0aW9uLnJlbW90ZUFkZHJlc3NcblxuICAgICAgICAvLyDor7fmsYLlpITnkIZcbiAgICAgICAgbGV0IG91dCA9IGF3YWl0IHJlcXVlc3RfcHJvY2VzcyhfX2FwaV9fLCBwYXJhbSlcblxuICAgICAgICAvLyDlpITnkIZyZXNwb25zZeeahGNvb2tpZXPorr7nva5cbiAgICAgICAgaWYgKCFfLmlzRW1wdHkoZ2xvYmFsWydfX3Jlc3BvbmRfY29va2llc19fJ10pKSB7XG4gICAgICAgICAgICByZXMuc2V0SGVhZGVyKCdTZXQtQ29va2llJywgXy52YWx1ZXMoZ2xvYmFsWydfX3Jlc3BvbmRfY29va2llc19fJ10pKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdsb2JhbFsnX19yZWRpcmVjdF91cmxfXyddKSB7XG4gICAgICAgICAgICByZXMucmVkaXJlY3QoMzAyLCBnbG9iYWxbJ19fcmVkaXJlY3RfdXJsX18nXSlcbiAgICAgICAgICAgIGdsb2JhbFsnX19yZWRpcmVjdF91cmxfXyddID0gdW5kZWZpbmVkXG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICByZXMuc2VuZChvdXQpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIC8vIOmAmuefpeahhuaetuiHqui6q+WunueOsOmAu+i+keeahOaEj+WkluaKpemUme+8iOahhuaetuiHqui6q+S4jeiuuuS9leenjeaDheWGtemDveW6lOivpeato+W4uOW3peS9nO+8jOS4gOaXpuWHuueOsOatpOmXrumimOWkp+WkmuaVsOaDheWGteaYr+ahhuaetuiHqui6q+mXrumimOaIluiAhea1gemHj+W8leWPkeeahOi/kOe7tOmXrumimO+8iVxuICAgICAgICBhd2FpdCB4d2Fybih7XG4gICAgICAgICAgICBfX2FwaV9fLCBfX3VybF9fLCBwYXJhbSwgbWVzc2FnZTogZXJyLm1lc3NhZ2UsIHN0YWNrOiB4c3RhY2soZXJyKVxuICAgICAgICB9KVxuICAgICAgICAvLyA1MDBcdEludGVybmFsIFNlcnZlciBFcnJvclx05pyN5Yqh5Zmo5YaF6YOo6ZSZ6K+v77yM5peg5rOV5a6M5oiQ6K+35rGCXG4gICAgICAgIHJlcy5zZW5kU3RhdHVzKDUwMClcbiAgICB9XG59Il19
\No newline at end of file