UNPKG

14.9 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 return new (P || (P = Promise))(function (resolve, reject) {
5 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 step((generator = generator.apply(thisArg, _arguments || [])).next());
9 });
10};
11var __generator = (this && this.__generator) || function (thisArg, body) {
12 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14 function verb(n) { return function (v) { return step([n, v]); }; }
15 function step(op) {
16 if (f) throw new TypeError("Generator is already executing.");
17 while (_) try {
18 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;
19 if (y = 0, t) op = [op[0] & 2, t.value];
20 switch (op[0]) {
21 case 0: case 1: t = op; break;
22 case 4: _.label++; return { value: op[1], done: false };
23 case 5: _.label++; y = op[1]; op = [0]; continue;
24 case 7: op = _.ops.pop(); _.trys.pop(); continue;
25 default:
26 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30 if (t[2]) _.ops.pop();
31 _.trys.pop(); continue;
32 }
33 op = body.call(thisArg, _);
34 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36 }
37};
38Object.defineProperty(exports, "__esModule", { value: true });
39var logger_1 = require("@bitblit/ratchet/dist/common/logger");
40var http = require("http");
41var web_handler_1 = require("./http/web-handler");
42var promise_ratchet_1 = require("@bitblit/ratchet/dist/common/promise-ratchet");
43var string_ratchet_1 = require("@bitblit/ratchet/dist/common/string-ratchet");
44var moment = require("moment-timezone");
45var qs = require("querystring");
46var simple_role_route_auth_1 = require("./http/auth/simple-role-route-auth");
47var router_util_1 = require("./http/route/router-util");
48var fs = require("fs");
49var path = require("path");
50var built_in_handlers_1 = require("./http/route/built-in-handlers");
51var epsilon_constants_1 = require("./epsilon-constants");
52var error_ratchet_1 = require("@bitblit/ratchet/dist/common/error-ratchet");
53var number_ratchet_1 = require("@bitblit/ratchet/dist/common/number-ratchet");
54var event_util_1 = require("./http/event-util");
55/**
56 * A simplistic server for testing your lambdas locally
57 */
58var LocalServer = /** @class */ (function () {
59 function LocalServer(routerConfig, port) {
60 if (port === void 0) { port = 8888; }
61 this.routerConfig = routerConfig;
62 this.port = port;
63 this.aborted = false;
64 this.webHandler = new web_handler_1.WebHandler(routerConfig);
65 }
66 LocalServer.prototype.runServer = function () {
67 return __awaiter(this, void 0, void 0, function () {
68 var _this = this;
69 return __generator(this, function (_a) {
70 logger_1.Logger.info('Starting Epsilon server on port %d', this.port);
71 this.server = http.createServer(this.requestHandler.bind(this)).listen(this.port);
72 logger_1.Logger.info('Epsilon server is listening');
73 // Also listen for SIGINT
74 process.on('SIGINT', function () {
75 logger_1.Logger.info('Caught SIGINT - shutting down test server...');
76 _this.aborted = true;
77 });
78 return [2 /*return*/, this.checkFinished()];
79 });
80 });
81 };
82 LocalServer.prototype.checkFinished = function () {
83 return __awaiter(this, void 0, void 0, function () {
84 var wait;
85 return __generator(this, function (_a) {
86 switch (_a.label) {
87 case 0:
88 if (!this.aborted) return [3 /*break*/, 1];
89 return [2 /*return*/, true];
90 case 1: return [4 /*yield*/, promise_ratchet_1.PromiseRatchet.wait(1000)];
91 case 2:
92 wait = _a.sent();
93 return [2 /*return*/, this.checkFinished()];
94 }
95 });
96 });
97 };
98 LocalServer.prototype.requestHandler = function (request, response) {
99 return __awaiter(this, void 0, void 0, function () {
100 var evt, context, logEventLevel, result, written;
101 return __generator(this, function (_a) {
102 switch (_a.label) {
103 case 0: return [4 /*yield*/, this.messageToApiGatewayEvent(request)];
104 case 1:
105 evt = _a.sent();
106 context = {
107 awsRequestId: 'LOCAL-' + string_ratchet_1.StringRatchet.createType4Guid()
108 };
109 logEventLevel = event_util_1.EventUtil.eventIsAGraphQLIntrospection(evt) ? 'silly' : 'info';
110 logger_1.Logger.logByLevel(logEventLevel, 'Processing event: %j', evt);
111 if (!(evt.path == '/epsilon-poison-pill')) return [3 /*break*/, 2];
112 this.aborted = true;
113 return [2 /*return*/, true];
114 case 2: return [4 /*yield*/, this.webHandler.lambdaHandler(evt, context)];
115 case 3:
116 result = _a.sent();
117 return [4 /*yield*/, this.writeProxyResultToServerResponse(result, response)];
118 case 4:
119 written = _a.sent();
120 return [2 /*return*/, written];
121 }
122 });
123 });
124 };
125 LocalServer.prototype.bodyAsBase64String = function (request) {
126 return __awaiter(this, void 0, void 0, function () {
127 return __generator(this, function (_a) {
128 return [2 /*return*/, new Promise(function (res, rej) {
129 var body = [];
130 request.on('data', function (chunk) {
131 body.push(chunk);
132 });
133 request.on('end', function () {
134 var rval = Buffer.concat(body).toString('base64');
135 res(rval);
136 });
137 })];
138 });
139 });
140 };
141 LocalServer.prototype.messageToApiGatewayEvent = function (request) {
142 return __awaiter(this, void 0, void 0, function () {
143 var bodyString, stageIdx, stage, path, reqTime, formattedTime, queryIdx, queryStringParams, headers, rval;
144 return __generator(this, function (_a) {
145 switch (_a.label) {
146 case 0: return [4 /*yield*/, this.bodyAsBase64String(request)];
147 case 1:
148 bodyString = _a.sent();
149 stageIdx = request.url.indexOf('/', 1);
150 stage = request.url.substring(1, stageIdx);
151 path = request.url.substring(stageIdx + 1);
152 reqTime = new Date().getTime();
153 formattedTime = moment.tz(reqTime, 'UTC').format('DD/MMM/YYYY:hh:mm:ss ZZ');
154 queryIdx = request.url.indexOf('?');
155 queryStringParams = queryIdx > -1 ? qs.parse(request.url.substring(queryIdx + 1)) : {};
156 headers = Object.assign({}, request.headers);
157 headers['X-Forwarded-Proto'] = 'http'; // This server is always unencrypted
158 rval = {
159 body: bodyString,
160 multiValueHeaders: {},
161 multiValueQueryStringParameters: {},
162 resource: '/{proxy+}',
163 path: request.url,
164 httpMethod: request.method.toLowerCase(),
165 isBase64Encoded: true,
166 queryStringParameters: queryStringParams,
167 pathParameters: {
168 proxy: path
169 },
170 stageVariables: {
171 baz: 'qux'
172 },
173 headers: headers,
174 requestContext: {
175 accountId: '123456789012',
176 resourceId: '123456',
177 stage: stage,
178 requestId: string_ratchet_1.StringRatchet.createType4Guid(),
179 requestTime: formattedTime,
180 requestTimeEpoch: reqTime,
181 identity: null,
182 /*
183 identity: {
184 apiKey: null,
185 cognitoIdentityPoolId: null,
186 accountId: null,
187 cognitoIdentityId: null,
188 caller: null,
189 accessKey: null,
190 sourceIp: '127.0.0.1',
191 cognitoAuthenticationType: null,
192 cognitoAuthenticationProvider: null,
193 userArn: null,
194 userAgent: 'Custom User Agent String',
195 user: null
196 },
197 */
198 path: request.url,
199 domainName: request.headers['host'],
200 resourcePath: '/{proxy+}',
201 httpMethod: request.method.toLowerCase(),
202 apiId: '1234567890',
203 protocol: 'HTTP/1.1'
204 }
205 };
206 return [2 /*return*/, rval];
207 }
208 });
209 });
210 };
211 LocalServer.prototype.writeProxyResultToServerResponse = function (proxyResult, response) {
212 return __awaiter(this, void 0, void 0, function () {
213 var isGraphQLSchemaResponse, toWrite;
214 return __generator(this, function (_a) {
215 isGraphQLSchemaResponse = !!proxyResult && !!proxyResult.body && proxyResult.body.indexOf('{"data":{"__schema"') > -1;
216 if (!isGraphQLSchemaResponse) {
217 logger_1.Logger.debug('Result: %j', proxyResult);
218 }
219 response.statusCode = proxyResult.statusCode;
220 if (proxyResult.headers) {
221 Object.keys(proxyResult.headers).forEach(function (hk) {
222 response.setHeader(hk, String(proxyResult.headers[hk]));
223 });
224 }
225 toWrite = proxyResult.isBase64Encoded ? Buffer.from(proxyResult.body, 'base64') : Buffer.from(proxyResult.body);
226 response.end(toWrite);
227 return [2 /*return*/, !!proxyResult.body];
228 });
229 });
230 };
231 return LocalServer;
232}());
233exports.LocalServer = LocalServer;
234// Functions below here are for using as samples
235function createSampleRouterConfig() {
236 var yamlString = loadSampleOpenApiYaml();
237 var authorizers = new Map();
238 var handlers = new Map();
239 var simpleRouteAuth = new simple_role_route_auth_1.SimpleRoleRouteAuth(['USER'], []);
240 authorizers.set('SampleAuthorizer', function (token, event, route) { return simpleRouteAuth.handler(token, event, route); });
241 handlers.set('get /', function (event, context) { return built_in_handlers_1.BuiltInHandlers.sample(event, null, context); });
242 handlers.set('get /meta/server', function (event) { return built_in_handlers_1.BuiltInHandlers.sample(event); });
243 handlers.set('get /meta/user', function (event) { return built_in_handlers_1.BuiltInHandlers.sample(event); });
244 handlers.set('get /meta/item/{itemId}', function (event) { return built_in_handlers_1.BuiltInHandlers.sample(event); });
245 handlers.set('post /secure/access-token', function (event) { return built_in_handlers_1.BuiltInHandlers.sample(event); });
246 handlers.set('get /multi/fixed', function (event) { return built_in_handlers_1.BuiltInHandlers.sample(event, 'fixed'); });
247 handlers.set('get /multi/{v}', function (event) { return built_in_handlers_1.BuiltInHandlers.sample(event, 'variable'); });
248 handlers.set('get /err/{code}', function (event) {
249 var err = error_ratchet_1.ErrorRatchet.fErr('Fake Err : %j', event);
250 err['statusCode'] = number_ratchet_1.NumberRatchet.safeNumber(event.pathParameters['code']);
251 throw err;
252 });
253 var cfg = router_util_1.RouterUtil.openApiYamlToRouterConfig(yamlString, handlers, authorizers);
254 cfg.corsAllowedHeaders = epsilon_constants_1.EpsilonConstants.CORS_MATCH_REQUEST_FLAG;
255 cfg.corsAllowedOrigins = epsilon_constants_1.EpsilonConstants.CORS_MATCH_REQUEST_FLAG;
256 cfg.corsAllowedMethods = epsilon_constants_1.EpsilonConstants.CORS_MATCH_REQUEST_FLAG;
257 cfg.defaultErrorMessage = 'Internal Server Error';
258 return cfg;
259}
260exports.createSampleRouterConfig = createSampleRouterConfig;
261function loadSampleOpenApiYaml() {
262 var yamlString = fs.readFileSync(path.join(__dirname, 'static', 'sample-open-api-doc.yaml')).toString();
263 return yamlString;
264}
265exports.loadSampleOpenApiYaml = loadSampleOpenApiYaml;
266//# sourceMappingURL=local-server.js.map
\No newline at end of file