serverless-offline 8.3.1 → 8.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +83 -10
- package/dist/ServerlessOffline.js +19 -2
- package/dist/config/commandOptions.js +4 -0
- package/dist/config/defaultOptions.js +1 -0
- package/dist/events/{http/authCanExecuteResource.js → authCanExecuteResource.js} +0 -0
- package/dist/events/{http/authFunctionNameExtractor.js → authFunctionNameExtractor.js} +1 -1
- package/dist/events/{http/authMatchPolicyResource.js → authMatchPolicyResource.js} +0 -0
- package/dist/events/http/HttpServer.js +48 -10
- package/dist/events/http/createAuthScheme.js +3 -2
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +21 -1
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +28 -2
- package/dist/events/websocket/WebSocketClients.js +259 -26
- package/dist/events/websocket/WebSocketServer.js +50 -4
- package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +99 -0
- package/dist/events/websocket/lambda-events/index.js +8 -0
- package/dist/lambda/LambdaFunction.js +3 -2
- package/dist/lambda/handler-runner/HandlerRunner.js +9 -1
- package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +9 -1
- package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +4 -1
- package/dist/lambda/handler-runner/go-runner/GoRunner.js +211 -0
- package/dist/lambda/handler-runner/go-runner/index.js +15 -0
- package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +28 -7
- package/dist/lambda/handler-runner/java-runner/JavaRunner.js +1 -2
- package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +0 -2
- package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +2 -0
- package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +3 -2
- package/dist/lambda/routes/invocations/invocationsRoute.js +2 -1
- package/dist/utils/checkGoVersion.js +27 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/splitHandlerPathAndName.js +13 -9
- package/package.json +48 -19
|
@@ -17,6 +17,10 @@ var _index2 = require("../../config/index.js");
|
|
|
17
17
|
|
|
18
18
|
var _index3 = require("../../utils/index.js");
|
|
19
19
|
|
|
20
|
+
var _authFunctionNameExtractor = _interopRequireDefault(require("../authFunctionNameExtractor.js"));
|
|
21
|
+
|
|
22
|
+
var _authCanExecuteResource = _interopRequireDefault(require("../authCanExecuteResource.js"));
|
|
23
|
+
|
|
20
24
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
25
|
|
|
22
26
|
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
|
|
@@ -36,8 +40,14 @@ var _lambda = /*#__PURE__*/_classPrivateFieldLooseKey("lambda");
|
|
|
36
40
|
|
|
37
41
|
var _options = /*#__PURE__*/_classPrivateFieldLooseKey("options");
|
|
38
42
|
|
|
43
|
+
var _serverless = /*#__PURE__*/_classPrivateFieldLooseKey("serverless");
|
|
44
|
+
|
|
39
45
|
var _webSocketRoutes = /*#__PURE__*/_classPrivateFieldLooseKey("webSocketRoutes");
|
|
40
46
|
|
|
47
|
+
var _webSocketAuthorizers = /*#__PURE__*/_classPrivateFieldLooseKey("webSocketAuthorizers");
|
|
48
|
+
|
|
49
|
+
var _webSocketAuthorizersCache = /*#__PURE__*/_classPrivateFieldLooseKey("webSocketAuthorizersCache");
|
|
50
|
+
|
|
41
51
|
var _websocketsApiRouteSelectionExpression = /*#__PURE__*/_classPrivateFieldLooseKey("websocketsApiRouteSelectionExpression");
|
|
42
52
|
|
|
43
53
|
var _idleTimeouts = /*#__PURE__*/_classPrivateFieldLooseKey("idleTimeouts");
|
|
@@ -58,10 +68,22 @@ class WebSocketClients {
|
|
|
58
68
|
writable: true,
|
|
59
69
|
value: null
|
|
60
70
|
});
|
|
71
|
+
Object.defineProperty(this, _serverless, {
|
|
72
|
+
writable: true,
|
|
73
|
+
value: null
|
|
74
|
+
});
|
|
61
75
|
Object.defineProperty(this, _webSocketRoutes, {
|
|
62
76
|
writable: true,
|
|
63
77
|
value: new Map()
|
|
64
78
|
});
|
|
79
|
+
Object.defineProperty(this, _webSocketAuthorizers, {
|
|
80
|
+
writable: true,
|
|
81
|
+
value: new Map()
|
|
82
|
+
});
|
|
83
|
+
Object.defineProperty(this, _webSocketAuthorizersCache, {
|
|
84
|
+
writable: true,
|
|
85
|
+
value: new Map()
|
|
86
|
+
});
|
|
65
87
|
Object.defineProperty(this, _websocketsApiRouteSelectionExpression, {
|
|
66
88
|
writable: true,
|
|
67
89
|
value: null
|
|
@@ -76,6 +98,7 @@ class WebSocketClients {
|
|
|
76
98
|
});
|
|
77
99
|
_classPrivateFieldLooseBase(this, _lambda)[_lambda] = lambda;
|
|
78
100
|
_classPrivateFieldLooseBase(this, _options)[_options] = options;
|
|
101
|
+
_classPrivateFieldLooseBase(this, _serverless)[_serverless] = serverless;
|
|
79
102
|
_classPrivateFieldLooseBase(this, _websocketsApiRouteSelectionExpression)[_websocketsApiRouteSelectionExpression] = serverless.service.provider.websocketsApiRouteSelectionExpression || _index2.DEFAULT_WEBSOCKETS_API_ROUTE_SELECTION_EXPRESSION;
|
|
80
103
|
|
|
81
104
|
if (v3Utils) {
|
|
@@ -160,14 +183,147 @@ class WebSocketClients {
|
|
|
160
183
|
clearTimeout(timeoutId);
|
|
161
184
|
}
|
|
162
185
|
|
|
163
|
-
async
|
|
164
|
-
|
|
186
|
+
async verifyClient(connectionId, request) {
|
|
187
|
+
const routeName = '$connect';
|
|
188
|
+
|
|
189
|
+
const route = _classPrivateFieldLooseBase(this, _webSocketRoutes)[_webSocketRoutes].get(routeName);
|
|
190
|
+
|
|
191
|
+
if (!route) {
|
|
192
|
+
return {
|
|
193
|
+
verified: false,
|
|
194
|
+
statusCode: 502
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const connectEvent = new _index.WebSocketConnectEvent(connectionId, request, _classPrivateFieldLooseBase(this, _options)[_options]).create();
|
|
199
|
+
|
|
200
|
+
const authFunName = _classPrivateFieldLooseBase(this, _webSocketAuthorizers)[_webSocketAuthorizers].get(routeName);
|
|
201
|
+
|
|
202
|
+
if (authFunName) {
|
|
203
|
+
const authorizerFunction = _classPrivateFieldLooseBase(this, _lambda)[_lambda].get(authFunName);
|
|
204
|
+
|
|
205
|
+
const authorizeEvent = new _index.WebSocketAuthorizerEvent(connectionId, request, _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider, _classPrivateFieldLooseBase(this, _options)[_options]).create();
|
|
206
|
+
authorizerFunction.setEvent(authorizeEvent);
|
|
207
|
+
|
|
208
|
+
if (this.log) {
|
|
209
|
+
this.log.notice();
|
|
210
|
+
this.log.notice(`Running Authorization function for ${routeName} (λ: ${authFunName})`);
|
|
211
|
+
} else {
|
|
212
|
+
console.log(''); // Just to make things a little pretty
|
|
213
|
+
|
|
214
|
+
(0, _serverlessLog.default)(`Running Authorization function for ${routeName} (λ: ${authFunName})`);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
try {
|
|
218
|
+
const result = await authorizerFunction.runHandler();
|
|
219
|
+
if (result === 'Unauthorized') return {
|
|
220
|
+
verified: false,
|
|
221
|
+
statusCode: 401
|
|
222
|
+
};
|
|
223
|
+
const policy = result; // Validate that the policy document has the principalId set
|
|
224
|
+
|
|
225
|
+
if (!policy.principalId) {
|
|
226
|
+
if (this.log) {
|
|
227
|
+
this.log.notice(`Authorization response did not include a principalId: (λ: ${authFunName})`);
|
|
228
|
+
} else {
|
|
229
|
+
(0, _serverlessLog.default)(`Authorization response did not include a principalId: (λ: ${authFunName})`);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
verified: false,
|
|
234
|
+
statusCode: 403
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (!(0, _authCanExecuteResource.default)(policy.policyDocument, authorizeEvent.methodArn)) {
|
|
239
|
+
if (this.log) {
|
|
240
|
+
this.log.notice(`Authorization response didn't authorize user to access resource: (λ: ${authFunName})`);
|
|
241
|
+
} else {
|
|
242
|
+
(0, _serverlessLog.default)(`Authorization response didn't authorize user to access resource: (λ: ${authFunName})`);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return {
|
|
246
|
+
verified: false,
|
|
247
|
+
statusCode: 403
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (this.log) {
|
|
252
|
+
this.log.notice(`Authorization function returned a successful response: (λ: ${authFunName})`);
|
|
253
|
+
} else {
|
|
254
|
+
(0, _serverlessLog.default)(`Authorization function returned a successful response: (λ: ${authFunName})`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
_classPrivateFieldLooseBase(this, _webSocketAuthorizersCache)[_webSocketAuthorizersCache].set(connectionId, {
|
|
258
|
+
identity: {
|
|
259
|
+
apiKey: policy.usageIdentifierKey,
|
|
260
|
+
sourceIp: authorizeEvent.requestContext.sourceIp,
|
|
261
|
+
userAgent: authorizeEvent.headers['user-agent'] || ''
|
|
262
|
+
},
|
|
263
|
+
authorizer: {
|
|
264
|
+
integrationLatency: '42',
|
|
265
|
+
principalId: policy.principalId,
|
|
266
|
+
...policy.context
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
} catch (err) {
|
|
270
|
+
if (this.log) {
|
|
271
|
+
this.log.debug(`Error in route handler '${routeName}' authorizer`, err);
|
|
272
|
+
} else {
|
|
273
|
+
(0, _debugLog.default)(`Error in route handler '${routeName}' authorizer`, err);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
verified: false,
|
|
278
|
+
statusCode: 500
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const authorizerData = _classPrivateFieldLooseBase(this, _webSocketAuthorizersCache)[_webSocketAuthorizersCache].get(connectionId);
|
|
284
|
+
|
|
285
|
+
if (authorizerData) {
|
|
286
|
+
connectEvent.identity = authorizerData.identity;
|
|
287
|
+
connectEvent.authorizer = authorizerData.authorizer;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const lambdaFunction = _classPrivateFieldLooseBase(this, _lambda)[_lambda].get(route.functionKey);
|
|
291
|
+
|
|
292
|
+
lambdaFunction.setEvent(connectEvent);
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
const {
|
|
296
|
+
statusCode
|
|
297
|
+
} = await lambdaFunction.runHandler();
|
|
298
|
+
const verified = statusCode >= 200 && statusCode < 300;
|
|
299
|
+
return {
|
|
300
|
+
verified,
|
|
301
|
+
statusCode
|
|
302
|
+
};
|
|
303
|
+
} catch (err) {
|
|
304
|
+
_classPrivateFieldLooseBase(this, _webSocketAuthorizersCache)[_webSocketAuthorizersCache].delete(connectionId);
|
|
305
|
+
|
|
306
|
+
if (this.log) {
|
|
307
|
+
this.log.debug(`Error in route handler '${route.functionKey}'`, err);
|
|
308
|
+
} else {
|
|
309
|
+
(0, _debugLog.default)(`Error in route handler '${route.functionKey}'`, err);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return {
|
|
313
|
+
verified: false,
|
|
314
|
+
statusCode: 502
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async _processEvent(websocketClient, connectionId, routeKey, event) {
|
|
320
|
+
let route = _classPrivateFieldLooseBase(this, _webSocketRoutes)[_webSocketRoutes].get(routeKey);
|
|
165
321
|
|
|
166
|
-
if (!
|
|
167
|
-
|
|
322
|
+
if (!route && routeKey !== '$disconnect') {
|
|
323
|
+
route = _classPrivateFieldLooseBase(this, _webSocketRoutes)[_webSocketRoutes].get('$default');
|
|
168
324
|
}
|
|
169
325
|
|
|
170
|
-
if (!
|
|
326
|
+
if (!route) {
|
|
171
327
|
return;
|
|
172
328
|
}
|
|
173
329
|
|
|
@@ -178,27 +334,30 @@ class WebSocketClients {
|
|
|
178
334
|
message: 'Internal server error',
|
|
179
335
|
requestId: '1234567890'
|
|
180
336
|
}));
|
|
181
|
-
} // mimic AWS behaviour (close connection) when the $connect route handler throws
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
if (route === '$connect') {
|
|
185
|
-
websocketClient.close();
|
|
186
337
|
}
|
|
187
338
|
|
|
188
339
|
if (this.log) {
|
|
189
|
-
this.log.debug(`Error in route handler '${functionKey}'`, err);
|
|
340
|
+
this.log.debug(`Error in route handler '${route.functionKey}'`, err);
|
|
190
341
|
} else {
|
|
191
|
-
(0, _debugLog.default)(`Error in route handler '${functionKey}'`, err);
|
|
342
|
+
(0, _debugLog.default)(`Error in route handler '${route.functionKey}'`, err);
|
|
192
343
|
}
|
|
193
344
|
};
|
|
194
345
|
|
|
195
|
-
const lambdaFunction = _classPrivateFieldLooseBase(this, _lambda)[_lambda].get(functionKey);
|
|
346
|
+
const lambdaFunction = _classPrivateFieldLooseBase(this, _lambda)[_lambda].get(route.functionKey);
|
|
196
347
|
|
|
197
|
-
lambdaFunction.setEvent(event);
|
|
348
|
+
lambdaFunction.setEvent(event);
|
|
198
349
|
|
|
199
350
|
try {
|
|
200
|
-
|
|
201
|
-
|
|
351
|
+
const {
|
|
352
|
+
body
|
|
353
|
+
} = await lambdaFunction.runHandler();
|
|
354
|
+
|
|
355
|
+
if (body && routeKey !== '$disconnect' && route.definition.routeResponseSelectionExpression === '$default') {
|
|
356
|
+
// https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-selection-expressions.html#apigateway-websocket-api-route-response-selection-expressions
|
|
357
|
+
// TODO: Once API gateway supports RouteResponses, this will need to change to support that functionality
|
|
358
|
+
// For now, send body back to the client
|
|
359
|
+
this.send(connectionId, body);
|
|
360
|
+
}
|
|
202
361
|
} catch (err) {
|
|
203
362
|
if (this.log) {
|
|
204
363
|
this.log.error(err);
|
|
@@ -230,13 +389,9 @@ class WebSocketClients {
|
|
|
230
389
|
return route || _index2.DEFAULT_WEBSOCKETS_ROUTE;
|
|
231
390
|
}
|
|
232
391
|
|
|
233
|
-
addClient(webSocketClient,
|
|
392
|
+
addClient(webSocketClient, connectionId) {
|
|
234
393
|
this._addWebSocketClient(webSocketClient, connectionId);
|
|
235
394
|
|
|
236
|
-
const connectEvent = new _index.WebSocketConnectEvent(connectionId, request, _classPrivateFieldLooseBase(this, _options)[_options]).create();
|
|
237
|
-
|
|
238
|
-
this._processEvent(webSocketClient, connectionId, '$connect', connectEvent);
|
|
239
|
-
|
|
240
395
|
webSocketClient.on('close', () => {
|
|
241
396
|
if (this.log) {
|
|
242
397
|
this.log.debug(`disconnect:${connectionId}`);
|
|
@@ -252,7 +407,14 @@ class WebSocketClients {
|
|
|
252
407
|
|
|
253
408
|
this._clearIdleTimeout(webSocketClient);
|
|
254
409
|
|
|
255
|
-
|
|
410
|
+
const authorizerData = _classPrivateFieldLooseBase(this, _webSocketAuthorizersCache)[_webSocketAuthorizersCache].get(connectionId);
|
|
411
|
+
|
|
412
|
+
if (authorizerData) {
|
|
413
|
+
disconnectEvent.identity = authorizerData.identity;
|
|
414
|
+
disconnectEvent.authorizer = authorizerData.authorizer;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
this._processEvent(webSocketClient, connectionId, '$disconnect', disconnectEvent).finally(() => _classPrivateFieldLooseBase(this, _webSocketAuthorizersCache)[_webSocketAuthorizersCache].delete(connectionId));
|
|
256
418
|
});
|
|
257
419
|
webSocketClient.on('message', message => {
|
|
258
420
|
if (this.log) {
|
|
@@ -271,20 +433,91 @@ class WebSocketClients {
|
|
|
271
433
|
|
|
272
434
|
const event = new _index.WebSocketEvent(connectionId, route, message).create();
|
|
273
435
|
|
|
436
|
+
const authorizerData = _classPrivateFieldLooseBase(this, _webSocketAuthorizersCache)[_webSocketAuthorizersCache].get(connectionId);
|
|
437
|
+
|
|
438
|
+
if (authorizerData) {
|
|
439
|
+
event.identity = authorizerData.identity;
|
|
440
|
+
event.authorizer = authorizerData.authorizer;
|
|
441
|
+
}
|
|
442
|
+
|
|
274
443
|
this._onWebSocketUsed(connectionId);
|
|
275
444
|
|
|
276
445
|
this._processEvent(webSocketClient, connectionId, route, event);
|
|
277
446
|
});
|
|
278
447
|
}
|
|
279
448
|
|
|
280
|
-
|
|
449
|
+
_extractAuthFunctionName(endpoint) {
|
|
450
|
+
if (typeof endpoint.authorizer === 'object' && endpoint.authorizer.type && endpoint.authorizer.type.toUpperCase() === 'TOKEN') {
|
|
451
|
+
if (this.log) {
|
|
452
|
+
this.log.debug(`Websockets does not support the TOKEN authorization type`);
|
|
453
|
+
} else {
|
|
454
|
+
(0, _debugLog.default)(`WARNING: Websockets does not support the TOKEN authorization type`);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
const result = (0, _authFunctionNameExtractor.default)(endpoint, null, this);
|
|
461
|
+
return result.unsupportedAuth ? null : result.authorizerName;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
_configureAuthorization(endpoint, functionKey) {
|
|
465
|
+
if (!endpoint.authorizer) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (endpoint.route === '$connect') {
|
|
470
|
+
const authFunctionName = this._extractAuthFunctionName(endpoint);
|
|
471
|
+
|
|
472
|
+
if (!authFunctionName) {
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
if (this.log) {
|
|
477
|
+
this.log.notice(`Configuring Authorization: ${functionKey} ${authFunctionName}`);
|
|
478
|
+
} else {
|
|
479
|
+
(0, _serverlessLog.default)(`Configuring Authorization: ${functionKey} ${authFunctionName}`);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
const authFunction = _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.getFunction(authFunctionName);
|
|
483
|
+
|
|
484
|
+
if (!authFunction) {
|
|
485
|
+
if (this.log) {
|
|
486
|
+
this.log.error(`Authorization function ${authFunctionName} does not exist`);
|
|
487
|
+
} else {
|
|
488
|
+
(0, _serverlessLog.default)(`WARNING: Authorization function ${authFunctionName} does not exist`);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
_classPrivateFieldLooseBase(this, _webSocketAuthorizers)[_webSocketAuthorizers].set(endpoint.route, authFunctionName);
|
|
495
|
+
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (this.log) {
|
|
500
|
+
this.log.notice(`Configuring Authorization is supported only on $connect route`);
|
|
501
|
+
} else {
|
|
502
|
+
(0, _serverlessLog.default)(`Configuring Authorization is supported only on $connect route`);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
addRoute(functionKey, definition) {
|
|
281
507
|
// set the route name
|
|
282
|
-
_classPrivateFieldLooseBase(this, _webSocketRoutes)[_webSocketRoutes].set(route,
|
|
508
|
+
_classPrivateFieldLooseBase(this, _webSocketRoutes)[_webSocketRoutes].set(definition.route, {
|
|
509
|
+
functionKey,
|
|
510
|
+
definition
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
if (!_classPrivateFieldLooseBase(this, _options)[_options].noAuth) {
|
|
514
|
+
this._configureAuthorization(definition, functionKey);
|
|
515
|
+
}
|
|
283
516
|
|
|
284
517
|
if (this.log) {
|
|
285
|
-
this.log.notice(`route '${
|
|
518
|
+
this.log.notice(`route '${definition}'`);
|
|
286
519
|
} else {
|
|
287
|
-
(0, _serverlessLog.default)(`route '${
|
|
520
|
+
(0, _serverlessLog.default)(`route '${definition}'`);
|
|
288
521
|
}
|
|
289
522
|
}
|
|
290
523
|
|
|
@@ -25,6 +25,8 @@ var _options = /*#__PURE__*/_classPrivateFieldLooseKey("options");
|
|
|
25
25
|
|
|
26
26
|
var _webSocketClients = /*#__PURE__*/_classPrivateFieldLooseKey("webSocketClients");
|
|
27
27
|
|
|
28
|
+
var _connectionIds = /*#__PURE__*/_classPrivateFieldLooseKey("connectionIds");
|
|
29
|
+
|
|
28
30
|
class WebSocketServer {
|
|
29
31
|
constructor(options, webSocketClients, sharedServer, v3Utils) {
|
|
30
32
|
Object.defineProperty(this, _options, {
|
|
@@ -35,6 +37,10 @@ class WebSocketServer {
|
|
|
35
37
|
writable: true,
|
|
36
38
|
value: null
|
|
37
39
|
});
|
|
40
|
+
Object.defineProperty(this, _connectionIds, {
|
|
41
|
+
writable: true,
|
|
42
|
+
value: new Map()
|
|
43
|
+
});
|
|
38
44
|
_classPrivateFieldLooseBase(this, _options)[_options] = options;
|
|
39
45
|
_classPrivateFieldLooseBase(this, _webSocketClients)[_webSocketClients] = webSocketClients;
|
|
40
46
|
|
|
@@ -46,7 +52,42 @@ class WebSocketServer {
|
|
|
46
52
|
}
|
|
47
53
|
|
|
48
54
|
const server = new _ws.Server({
|
|
49
|
-
server: sharedServer
|
|
55
|
+
server: sharedServer,
|
|
56
|
+
verifyClient: ({
|
|
57
|
+
req
|
|
58
|
+
}, cb) => {
|
|
59
|
+
const connectionId = (0, _index.createUniqueId)();
|
|
60
|
+
const {
|
|
61
|
+
headers
|
|
62
|
+
} = req;
|
|
63
|
+
const key = headers['sec-websocket-key'];
|
|
64
|
+
|
|
65
|
+
if (this.log) {
|
|
66
|
+
this.log.debug(`verifyClient:${key} ${connectionId}`);
|
|
67
|
+
} else {
|
|
68
|
+
(0, _debugLog.default)(`verifyClient:${key} ${connectionId}`);
|
|
69
|
+
} // Use the websocket key to coorelate connection IDs
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
_classPrivateFieldLooseBase(this, _connectionIds)[_connectionIds][key] = connectionId;
|
|
73
|
+
|
|
74
|
+
_classPrivateFieldLooseBase(this, _webSocketClients)[_webSocketClients].verifyClient(connectionId, req).then(({
|
|
75
|
+
verified,
|
|
76
|
+
statusCode
|
|
77
|
+
}) => {
|
|
78
|
+
try {
|
|
79
|
+
if (!verified) {
|
|
80
|
+
cb(false, statusCode);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
cb(true);
|
|
85
|
+
} catch (e) {
|
|
86
|
+
(0, _debugLog.default)(`Error verifying`, e);
|
|
87
|
+
cb(false);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
50
91
|
});
|
|
51
92
|
server.on('connection', (webSocketClient, request) => {
|
|
52
93
|
if (this.log) {
|
|
@@ -55,7 +96,12 @@ class WebSocketServer {
|
|
|
55
96
|
console.log('received connection');
|
|
56
97
|
}
|
|
57
98
|
|
|
58
|
-
const
|
|
99
|
+
const {
|
|
100
|
+
headers
|
|
101
|
+
} = request;
|
|
102
|
+
const key = headers['sec-websocket-key'];
|
|
103
|
+
|
|
104
|
+
const connectionId = _classPrivateFieldLooseBase(this, _connectionIds)[_connectionIds][key];
|
|
59
105
|
|
|
60
106
|
if (this.log) {
|
|
61
107
|
this.log.debug(`connect:${connectionId}`);
|
|
@@ -63,7 +109,7 @@ class WebSocketServer {
|
|
|
63
109
|
(0, _debugLog.default)(`connect:${connectionId}`);
|
|
64
110
|
}
|
|
65
111
|
|
|
66
|
-
_classPrivateFieldLooseBase(this, _webSocketClients)[_webSocketClients].addClient(webSocketClient,
|
|
112
|
+
_classPrivateFieldLooseBase(this, _webSocketClients)[_webSocketClients].addClient(webSocketClient, connectionId);
|
|
67
113
|
});
|
|
68
114
|
}
|
|
69
115
|
|
|
@@ -85,7 +131,7 @@ class WebSocketServer {
|
|
|
85
131
|
stop() {}
|
|
86
132
|
|
|
87
133
|
addRoute(functionKey, webSocketEvent) {
|
|
88
|
-
_classPrivateFieldLooseBase(this, _webSocketClients)[_webSocketClients].addRoute(functionKey, webSocketEvent
|
|
134
|
+
_classPrivateFieldLooseBase(this, _webSocketClients)[_webSocketClients].addRoute(functionKey, webSocketEvent); // serverlessLog(`route '${route}'`)
|
|
89
135
|
|
|
90
136
|
}
|
|
91
137
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _WebSocketRequestContext = _interopRequireDefault(require("./WebSocketRequestContext.js"));
|
|
9
|
+
|
|
10
|
+
var _index = require("../../../utils/index.js");
|
|
11
|
+
|
|
12
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
|
|
14
|
+
function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
|
|
15
|
+
|
|
16
|
+
var id = 0;
|
|
17
|
+
|
|
18
|
+
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
19
|
+
|
|
20
|
+
var _connectionId = /*#__PURE__*/_classPrivateFieldLooseKey("connectionId");
|
|
21
|
+
|
|
22
|
+
var _httpsProtocol = /*#__PURE__*/_classPrivateFieldLooseKey("httpsProtocol");
|
|
23
|
+
|
|
24
|
+
var _rawHeaders = /*#__PURE__*/_classPrivateFieldLooseKey("rawHeaders");
|
|
25
|
+
|
|
26
|
+
var _url = /*#__PURE__*/_classPrivateFieldLooseKey("url");
|
|
27
|
+
|
|
28
|
+
var _websocketPort = /*#__PURE__*/_classPrivateFieldLooseKey("websocketPort");
|
|
29
|
+
|
|
30
|
+
var _provider = /*#__PURE__*/_classPrivateFieldLooseKey("provider");
|
|
31
|
+
|
|
32
|
+
class WebSocketAuthorizerEvent {
|
|
33
|
+
constructor(connectionId, request, provider, options) {
|
|
34
|
+
Object.defineProperty(this, _connectionId, {
|
|
35
|
+
writable: true,
|
|
36
|
+
value: null
|
|
37
|
+
});
|
|
38
|
+
Object.defineProperty(this, _httpsProtocol, {
|
|
39
|
+
writable: true,
|
|
40
|
+
value: null
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, _rawHeaders, {
|
|
43
|
+
writable: true,
|
|
44
|
+
value: null
|
|
45
|
+
});
|
|
46
|
+
Object.defineProperty(this, _url, {
|
|
47
|
+
writable: true,
|
|
48
|
+
value: null
|
|
49
|
+
});
|
|
50
|
+
Object.defineProperty(this, _websocketPort, {
|
|
51
|
+
writable: true,
|
|
52
|
+
value: null
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(this, _provider, {
|
|
55
|
+
writable: true,
|
|
56
|
+
value: null
|
|
57
|
+
});
|
|
58
|
+
const {
|
|
59
|
+
httpsProtocol,
|
|
60
|
+
websocketPort
|
|
61
|
+
} = options;
|
|
62
|
+
const {
|
|
63
|
+
rawHeaders,
|
|
64
|
+
url
|
|
65
|
+
} = request;
|
|
66
|
+
_classPrivateFieldLooseBase(this, _connectionId)[_connectionId] = connectionId;
|
|
67
|
+
_classPrivateFieldLooseBase(this, _httpsProtocol)[_httpsProtocol] = httpsProtocol;
|
|
68
|
+
_classPrivateFieldLooseBase(this, _rawHeaders)[_rawHeaders] = rawHeaders;
|
|
69
|
+
_classPrivateFieldLooseBase(this, _url)[_url] = url;
|
|
70
|
+
_classPrivateFieldLooseBase(this, _websocketPort)[_websocketPort] = websocketPort;
|
|
71
|
+
_classPrivateFieldLooseBase(this, _provider)[_provider] = provider;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
create() {
|
|
75
|
+
const headers = (0, _index.parseHeaders)(_classPrivateFieldLooseBase(this, _rawHeaders)[_rawHeaders]);
|
|
76
|
+
const multiValueHeaders = (0, _index.parseMultiValueHeaders)(_classPrivateFieldLooseBase(this, _rawHeaders)[_rawHeaders]);
|
|
77
|
+
const multiValueQueryStringParameters = (0, _index.parseMultiValueQueryStringParameters)(_classPrivateFieldLooseBase(this, _url)[_url]);
|
|
78
|
+
const queryStringParameters = (0, _index.parseQueryStringParameters)(_classPrivateFieldLooseBase(this, _url)[_url]);
|
|
79
|
+
const requestContext = new _WebSocketRequestContext.default('CONNECT', '$connect', _classPrivateFieldLooseBase(this, _connectionId)[_connectionId]).create();
|
|
80
|
+
return {
|
|
81
|
+
type: 'REQUEST',
|
|
82
|
+
methodArn: `arn:aws:execute-api:${_classPrivateFieldLooseBase(this, _provider)[_provider].region}:${requestContext.accountId}:${requestContext.apiId}/${requestContext.stage}/${requestContext.routeKey}`,
|
|
83
|
+
headers,
|
|
84
|
+
multiValueHeaders,
|
|
85
|
+
// NOTE: multiValueQueryStringParameters and queryStringParameters
|
|
86
|
+
// properties are only defined if they have values
|
|
87
|
+
...(multiValueQueryStringParameters && {
|
|
88
|
+
multiValueQueryStringParameters
|
|
89
|
+
}),
|
|
90
|
+
...(queryStringParameters && {
|
|
91
|
+
queryStringParameters
|
|
92
|
+
}),
|
|
93
|
+
requestContext
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.default = WebSocketAuthorizerEvent;
|
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "WebSocketAuthorizerEvent", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _WebSocketAuthorizerEvent.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "WebSocketConnectEvent", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
@@ -28,4 +34,6 @@ var _WebSocketDisconnectEvent = _interopRequireDefault(require("./WebSocketDisco
|
|
|
28
34
|
|
|
29
35
|
var _WebSocketEvent = _interopRequireDefault(require("./WebSocketEvent.js"));
|
|
30
36
|
|
|
37
|
+
var _WebSocketAuthorizerEvent = _interopRequireDefault(require("./WebSocketAuthorizerEvent.js"));
|
|
38
|
+
|
|
31
39
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -177,7 +177,7 @@ class LambdaFunction {
|
|
|
177
177
|
name,
|
|
178
178
|
package: functionPackage = {}
|
|
179
179
|
} = functionDefinition;
|
|
180
|
-
const [handlerPath, handlerName] = (0, _index3.splitHandlerPathAndName)(handler);
|
|
180
|
+
const [handlerPath, handlerName, handlerModuleNesting] = (0, _index3.splitHandlerPathAndName)(handler);
|
|
181
181
|
const memorySize = functionDefinition.memorySize || provider.memorySize || _index2.DEFAULT_LAMBDA_MEMORY_SIZE;
|
|
182
182
|
const runtime = functionDefinition.runtime || provider.runtime || _index2.DEFAULT_LAMBDA_RUNTIME;
|
|
183
183
|
const timeout = (functionDefinition.timeout || provider.timeout || _index2.DEFAULT_LAMBDA_TIMEOUT) * 1000; // this._executionTimeout = null
|
|
@@ -212,6 +212,7 @@ class LambdaFunction {
|
|
|
212
212
|
functionKey,
|
|
213
213
|
handler,
|
|
214
214
|
handlerName,
|
|
215
|
+
handlerModuleNesting,
|
|
215
216
|
codeDir: _classPrivateFieldLooseBase(this, _codeDir)[_codeDir],
|
|
216
217
|
handlerPath: (0, _path.resolve)(_classPrivateFieldLooseBase(this, _codeDir)[_codeDir], handlerPath),
|
|
217
218
|
runtime,
|
|
@@ -269,7 +270,7 @@ class LambdaFunction {
|
|
|
269
270
|
LAMBDA_RUNTIME_DIR: '/var/runtime',
|
|
270
271
|
LAMBDA_TASK_ROOT: '/var/task',
|
|
271
272
|
LANG: 'en_US.UTF-8',
|
|
272
|
-
LD_LIBRARY_PATH: '/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib',
|
|
273
|
+
LD_LIBRARY_PATH: '/usr/local/lib64/node-v4.3.x/lib:/lib64:/usr/lib64:/var/runtime:/var/runtime/lib:/var/task:/var/task/lib:/opt/lib',
|
|
273
274
|
NODE_PATH: '/var/runtime:/var/task:/var/runtime/node_modules'
|
|
274
275
|
};
|
|
275
276
|
}
|
|
@@ -75,6 +75,7 @@ class HandlerRunner {
|
|
|
75
75
|
functionKey,
|
|
76
76
|
handlerName,
|
|
77
77
|
handlerPath,
|
|
78
|
+
handlerModuleNesting,
|
|
78
79
|
runtime,
|
|
79
80
|
timeout
|
|
80
81
|
} = _classPrivateFieldLooseBase(this, _funOptions)[_funOptions];
|
|
@@ -141,7 +142,14 @@ class HandlerRunner {
|
|
|
141
142
|
const {
|
|
142
143
|
default: InProcessRunner
|
|
143
144
|
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./in-process-runner/index.js')));
|
|
144
|
-
return new InProcessRunner(functionKey, handlerPath, handlerName, _classPrivateFieldLooseBase(this, _env)[_env], timeout, allowCache);
|
|
145
|
+
return new InProcessRunner(functionKey, handlerPath, handlerName, handlerModuleNesting, _classPrivateFieldLooseBase(this, _env)[_env], timeout, allowCache);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (_index.supportedGo.has(runtime)) {
|
|
149
|
+
const {
|
|
150
|
+
default: GoRunner
|
|
151
|
+
} = await Promise.resolve().then(() => _interopRequireWildcard(require('./go-runner/index.js')));
|
|
152
|
+
return new GoRunner(_classPrivateFieldLooseBase(this, _funOptions)[_funOptions], _classPrivateFieldLooseBase(this, _env)[_env], this.v3Utils);
|
|
145
153
|
}
|
|
146
154
|
|
|
147
155
|
if (_index.supportedPython.has(runtime)) {
|
|
@@ -27,6 +27,8 @@ var _handlerName = /*#__PURE__*/_classPrivateFieldLooseKey("handlerName");
|
|
|
27
27
|
|
|
28
28
|
var _handlerPath = /*#__PURE__*/_classPrivateFieldLooseKey("handlerPath");
|
|
29
29
|
|
|
30
|
+
var _handlerModuleNesting = /*#__PURE__*/_classPrivateFieldLooseKey("handlerModuleNesting");
|
|
31
|
+
|
|
30
32
|
var _timeout = /*#__PURE__*/_classPrivateFieldLooseKey("timeout");
|
|
31
33
|
|
|
32
34
|
var _allowCache = /*#__PURE__*/_classPrivateFieldLooseKey("allowCache");
|
|
@@ -49,6 +51,10 @@ class ChildProcessRunner {
|
|
|
49
51
|
writable: true,
|
|
50
52
|
value: null
|
|
51
53
|
});
|
|
54
|
+
Object.defineProperty(this, _handlerModuleNesting, {
|
|
55
|
+
writable: true,
|
|
56
|
+
value: null
|
|
57
|
+
});
|
|
52
58
|
Object.defineProperty(this, _timeout, {
|
|
53
59
|
writable: true,
|
|
54
60
|
value: null
|
|
@@ -61,6 +67,7 @@ class ChildProcessRunner {
|
|
|
61
67
|
functionKey,
|
|
62
68
|
handlerName,
|
|
63
69
|
handlerPath,
|
|
70
|
+
handlerModuleNesting,
|
|
64
71
|
timeout
|
|
65
72
|
} = funOptions;
|
|
66
73
|
|
|
@@ -75,6 +82,7 @@ class ChildProcessRunner {
|
|
|
75
82
|
_classPrivateFieldLooseBase(this, _functionKey)[_functionKey] = functionKey;
|
|
76
83
|
_classPrivateFieldLooseBase(this, _handlerName)[_handlerName] = handlerName;
|
|
77
84
|
_classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath] = handlerPath;
|
|
85
|
+
_classPrivateFieldLooseBase(this, _handlerModuleNesting)[_handlerModuleNesting] = handlerModuleNesting;
|
|
78
86
|
_classPrivateFieldLooseBase(this, _timeout)[_timeout] = timeout;
|
|
79
87
|
_classPrivateFieldLooseBase(this, _allowCache)[_allowCache] = allowCache;
|
|
80
88
|
} // no-op
|
|
@@ -84,7 +92,7 @@ class ChildProcessRunner {
|
|
|
84
92
|
cleanup() {}
|
|
85
93
|
|
|
86
94
|
async run(event, context) {
|
|
87
|
-
const childProcess = (0, _execa.node)(childProcessHelperPath, [_classPrivateFieldLooseBase(this, _functionKey)[_functionKey], _classPrivateFieldLooseBase(this, _handlerName)[_handlerName], _classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath]], {
|
|
95
|
+
const childProcess = (0, _execa.node)(childProcessHelperPath, [_classPrivateFieldLooseBase(this, _functionKey)[_functionKey], _classPrivateFieldLooseBase(this, _handlerName)[_handlerName], _classPrivateFieldLooseBase(this, _handlerPath)[_handlerPath], _classPrivateFieldLooseBase(this, _handlerModuleNesting)[_handlerModuleNesting]], {
|
|
88
96
|
env: _classPrivateFieldLooseBase(this, _env)[_env],
|
|
89
97
|
stdio: 'inherit'
|
|
90
98
|
});
|