serverless-offline 8.2.0 → 8.5.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.
Files changed (57) hide show
  1. package/README.md +157 -116
  2. package/dist/ServerlessOffline.js +98 -26
  3. package/dist/config/commandOptions.js +4 -0
  4. package/dist/config/constants.js +1 -1
  5. package/dist/config/defaultOptions.js +1 -0
  6. package/dist/events/http/Endpoint.js +27 -9
  7. package/dist/events/http/Http.js +3 -3
  8. package/dist/events/http/HttpServer.js +355 -82
  9. package/dist/events/http/authFunctionNameExtractor.js +14 -8
  10. package/dist/events/http/authJWTSettingsExtractor.js +14 -7
  11. package/dist/events/http/createAuthScheme.js +44 -9
  12. package/dist/events/http/createJWTAuthScheme.js +52 -13
  13. package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +7 -6
  14. package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +38 -7
  15. package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +37 -6
  16. package/dist/events/http/lambda-events/VelocityContext.js +4 -4
  17. package/dist/events/http/lambda-events/index.js +4 -4
  18. package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +19 -7
  19. package/dist/events/schedule/Schedule.js +45 -10
  20. package/dist/events/websocket/HttpServer.js +24 -7
  21. package/dist/events/websocket/WebSocket.js +14 -6
  22. package/dist/events/websocket/WebSocketClients.js +127 -38
  23. package/dist/events/websocket/WebSocketServer.js +79 -11
  24. package/dist/events/websocket/http-routes/_catchAll/catchAllRoute.js +9 -2
  25. package/dist/events/websocket/http-routes/connections/ConnectionsController.js +1 -1
  26. package/dist/events/websocket/http-routes/connections/connectionsRoutes.js +28 -5
  27. package/dist/events/websocket/lambda-events/WebSocketConnectEvent.js +5 -5
  28. package/dist/events/websocket/lambda-events/WebSocketDisconnectEvent.js +1 -1
  29. package/dist/events/websocket/lambda-events/WebSocketEvent.js +3 -3
  30. package/dist/events/websocket/lambda-events/WebSocketRequestContext.js +4 -4
  31. package/dist/lambda/HttpServer.js +34 -10
  32. package/dist/lambda/Lambda.js +15 -7
  33. package/dist/lambda/LambdaContext.js +1 -1
  34. package/dist/lambda/LambdaFunction.js +40 -23
  35. package/dist/lambda/LambdaFunctionPool.js +9 -8
  36. package/dist/lambda/handler-runner/HandlerRunner.js +51 -16
  37. package/dist/lambda/handler-runner/child-process-runner/ChildProcessRunner.js +21 -8
  38. package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +1 -10
  39. package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +168 -69
  40. package/dist/lambda/handler-runner/docker-runner/DockerImage.js +21 -5
  41. package/dist/lambda/handler-runner/docker-runner/DockerRunner.js +4 -4
  42. package/dist/lambda/handler-runner/go-runner/GoRunner.js +211 -0
  43. package/dist/lambda/handler-runner/go-runner/index.js +15 -0
  44. package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +16 -22
  45. package/dist/lambda/handler-runner/java-runner/JavaRunner.js +26 -14
  46. package/dist/lambda/handler-runner/python-runner/PythonRunner.js +20 -7
  47. package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +22 -24
  48. package/dist/lambda/handler-runner/worker-thread-runner/WorkerThreadRunner.js +2 -2
  49. package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +1 -11
  50. package/dist/lambda/routes/invocations/InvocationsController.js +30 -11
  51. package/dist/lambda/routes/invocations/invocationsRoute.js +4 -3
  52. package/dist/lambda/routes/invoke-async/InvokeAsyncController.js +2 -6
  53. package/dist/serverlessLog.js +1 -1
  54. package/dist/utils/checkGoVersion.js +27 -0
  55. package/dist/utils/getHttpApiCorsConfig.js +18 -5
  56. package/dist/utils/index.js +24 -16
  57. package/package.json +86 -37
@@ -9,12 +9,14 @@ var _buffer = require("buffer");
9
9
 
10
10
  var _fs = require("fs");
11
11
 
12
- var _path = require("path");
12
+ var pathUtils = _interopRequireWildcard(require("path"));
13
13
 
14
14
  var _h2o = _interopRequireDefault(require("@hapi/h2o2"));
15
15
 
16
16
  var _hapi = require("@hapi/hapi");
17
17
 
18
+ var _module = require("module");
19
+
18
20
  var _authFunctionNameExtractor = _interopRequireDefault(require("./authFunctionNameExtractor.js"));
19
21
 
20
22
  var _authJWTSettingsExtractor = _interopRequireDefault(require("./authJWTSettingsExtractor.js"));
@@ -39,11 +41,11 @@ var _index2 = require("../../utils/index.js");
39
41
 
40
42
  var _LambdaProxyIntegrationEventV = _interopRequireDefault(require("./lambda-events/LambdaProxyIntegrationEventV2.js"));
41
43
 
42
- function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
44
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
43
45
 
44
- function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
46
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
45
47
 
46
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
48
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
47
49
 
48
50
  function _classPrivateFieldLooseBase(receiver, privateKey) { if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) { throw new TypeError("attempted to use private field on non-instance"); } return receiver; }
49
51
 
@@ -56,20 +58,20 @@ const {
56
58
  stringify
57
59
  } = JSON;
58
60
 
59
- var _lambda = _classPrivateFieldLooseKey("lambda");
61
+ var _lambda = /*#__PURE__*/_classPrivateFieldLooseKey("lambda");
60
62
 
61
- var _lastRequestOptions = _classPrivateFieldLooseKey("lastRequestOptions");
63
+ var _lastRequestOptions = /*#__PURE__*/_classPrivateFieldLooseKey("lastRequestOptions");
62
64
 
63
- var _options = _classPrivateFieldLooseKey("options");
65
+ var _options = /*#__PURE__*/_classPrivateFieldLooseKey("options");
64
66
 
65
- var _serverless = _classPrivateFieldLooseKey("serverless");
67
+ var _serverless = /*#__PURE__*/_classPrivateFieldLooseKey("serverless");
66
68
 
67
- var _server = _classPrivateFieldLooseKey("server");
69
+ var _server = /*#__PURE__*/_classPrivateFieldLooseKey("server");
68
70
 
69
- var _terminalInfo = _classPrivateFieldLooseKey("terminalInfo");
71
+ var _terminalInfo = /*#__PURE__*/_classPrivateFieldLooseKey("terminalInfo");
70
72
 
71
73
  class HttpServer {
72
- constructor(serverless, options, lambda) {
74
+ constructor(serverless, options, lambda, v3Utils) {
73
75
  Object.defineProperty(this, _lambda, {
74
76
  writable: true,
75
77
  value: null
@@ -98,6 +100,13 @@ class HttpServer {
98
100
  _classPrivateFieldLooseBase(this, _options)[_options] = options;
99
101
  _classPrivateFieldLooseBase(this, _serverless)[_serverless] = serverless;
100
102
 
103
+ if (v3Utils) {
104
+ this.log = v3Utils.log;
105
+ this.progress = v3Utils.progress;
106
+ this.writeText = v3Utils.writeText;
107
+ this.v3Utils = v3Utils;
108
+ }
109
+
101
110
  const {
102
111
  enforceSecureCookies,
103
112
  host,
@@ -127,8 +136,8 @@ class HttpServer {
127
136
 
128
137
  if (typeof httpsProtocol === 'string' && httpsProtocol.length > 0) {
129
138
  serverOptions.tls = {
130
- cert: (0, _fs.readFileSync)((0, _path.resolve)(httpsProtocol, 'cert.pem'), 'ascii'),
131
- key: (0, _fs.readFileSync)((0, _path.resolve)(httpsProtocol, 'key.pem'), 'ascii')
139
+ cert: (0, _fs.readFileSync)((0, pathUtils.resolve)(httpsProtocol, 'cert.pem'), 'ascii'),
140
+ key: (0, _fs.readFileSync)((0, pathUtils.resolve)(httpsProtocol, 'key.pem'), 'ascii')
132
141
  };
133
142
  } // Hapijs server creation
134
143
 
@@ -142,7 +151,7 @@ class HttpServer {
142
151
  };
143
152
 
144
153
  if (_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi && _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi.cors) {
145
- const httpApiCors = (0, _index2.getHttpApiCorsConfig)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi.cors);
154
+ const httpApiCors = (0, _index2.getHttpApiCorsConfig)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi.cors, this);
146
155
 
147
156
  if (request.method === 'options') {
148
157
  response.statusCode = 204;
@@ -223,18 +232,30 @@ class HttpServer {
223
232
  try {
224
233
  await _classPrivateFieldLooseBase(this, _server)[_server].start();
225
234
  } catch (err) {
226
- console.error(`Unexpected error while starting serverless-offline server on port ${httpPort}:`, err);
235
+ if (this.log) {
236
+ this.log.error(`Unexpected error while starting serverless-offline server on port ${httpPort}:`, err);
237
+ } else {
238
+ console.error(`Unexpected error while starting serverless-offline server on port ${httpPort}:`, err);
239
+ }
240
+
227
241
  process.exit(1);
228
242
  } // TODO move the following block
229
243
 
230
244
 
231
245
  const server = `${httpsProtocol ? 'https' : 'http'}://${host}:${httpPort}`;
232
- (0, _serverlessLog.default)(`[HTTP] server ready: ${server} 🚀`);
233
- (0, _serverlessLog.default)(''); // serverlessLog('OpenAPI/Swagger documentation:')
234
- // logRoute('GET', server, '/documentation')
235
- // serverlessLog('')
236
246
 
237
- (0, _serverlessLog.default)('Enter "rp" to replay the last request');
247
+ if (this.log) {
248
+ this.log.notice(`Server ready: ${server} 🚀`);
249
+ this.log.notice();
250
+ this.log.notice('Enter "rp" to replay the last request');
251
+ } else {
252
+ (0, _serverlessLog.default)(`[HTTP] server ready: ${server} 🚀`);
253
+ (0, _serverlessLog.default)(''); // serverlessLog('OpenAPI/Swagger documentation:')
254
+ // logRoute('GET', server, '/documentation')
255
+ // serverlessLog('')
256
+
257
+ (0, _serverlessLog.default)('Enter "rp" to replay the last request');
258
+ }
238
259
 
239
260
  if (process.env.NODE_ENV !== 'test') {
240
261
  process.openStdin().addListener('data', data => {
@@ -259,7 +280,11 @@ class HttpServer {
259
280
  try {
260
281
  await _classPrivateFieldLooseBase(this, _server)[_server].register([_h2o.default]);
261
282
  } catch (err) {
262
- (0, _serverlessLog.default)(err);
283
+ if (this.log) {
284
+ this.log.error(err);
285
+ } else {
286
+ (0, _serverlessLog.default)(err);
287
+ }
263
288
  }
264
289
  } // // TODO unused:
265
290
  // get server() {
@@ -269,17 +294,26 @@ class HttpServer {
269
294
 
270
295
  _printBlankLine() {
271
296
  if (process.env.NODE_ENV !== 'test') {
272
- console.log();
297
+ if (this.log) {
298
+ this.log.notice();
299
+ } else {
300
+ console.log();
301
+ }
273
302
  }
274
303
  }
275
304
 
276
305
  _logPluginIssue() {
277
- (0, _serverlessLog.default)('If you think this is an issue with the plugin please submit it, thanks!');
278
- (0, _serverlessLog.default)('https://github.com/dherault/serverless-offline/issues');
306
+ if (this.log) {
307
+ this.log.notice('If you think this is an issue with the plugin please submit it, thanks!\nhttps://github.com/dherault/serverless-offline/issues');
308
+ this.log.notice();
309
+ } else {
310
+ (0, _serverlessLog.default)('If you think this is an issue with the plugin please submit it, thanks!');
311
+ (0, _serverlessLog.default)('https://github.com/dherault/serverless-offline/issues');
312
+ }
279
313
  }
280
314
 
281
315
  _extractJWTAuthSettings(endpoint) {
282
- const result = (0, _authJWTSettingsExtractor.default)(endpoint, _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider, _classPrivateFieldLooseBase(this, _options)[_options].ignoreJWTSignature);
316
+ const result = (0, _authJWTSettingsExtractor.default)(endpoint, _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider, _classPrivateFieldLooseBase(this, _options)[_options].ignoreJWTSignature, this);
283
317
  return result.unsupportedAuth ? null : result;
284
318
  }
285
319
 
@@ -300,16 +334,26 @@ class HttpServer {
300
334
  return null;
301
335
  }
302
336
 
303
- (0, _serverlessLog.default)(`Configuring JWT Authorization: ${method} ${path}`); // Create a unique scheme per endpoint
337
+ if (this.log) {
338
+ this.log.notice(`Configuring JWT Authorization: ${method} ${path}`);
339
+ } else {
340
+ (0, _serverlessLog.default)(`Configuring JWT Authorization: ${method} ${path}`);
341
+ } // Create a unique scheme per endpoint
304
342
  // This allows the methodArn on the event property to be set appropriately
305
343
 
344
+
306
345
  const authKey = `${functionKey}-${jwtSettings.authorizerName}-${method}-${path}`;
307
346
  const authSchemeName = `scheme-${authKey}`;
308
347
  const authStrategyName = `strategy-${authKey}`; // set strategy name for the route config
309
348
 
310
- (0, _debugLog.default)(`Creating Authorization scheme for ${authKey}`); // Create the Auth Scheme for the endpoint
349
+ if (this.log) {
350
+ this.log.debug(`Creating Authorization scheme for ${authKey}`);
351
+ } else {
352
+ (0, _debugLog.default)(`Creating Authorization scheme for ${authKey}`);
353
+ } // Create the Auth Scheme for the endpoint
311
354
 
312
- const scheme = (0, _createJWTAuthScheme.default)(jwtSettings); // Set the auth scheme and strategy on the server
355
+
356
+ const scheme = (0, _createJWTAuthScheme.default)(jwtSettings, this); // Set the auth scheme and strategy on the server
313
357
 
314
358
  _classPrivateFieldLooseBase(this, _server)[_server].auth.scheme(authSchemeName, scheme);
315
359
 
@@ -319,7 +363,7 @@ class HttpServer {
319
363
  }
320
364
 
321
365
  _extractAuthFunctionName(endpoint) {
322
- const result = (0, _authFunctionNameExtractor.default)(endpoint);
366
+ const result = (0, _authFunctionNameExtractor.default)(endpoint, null, this);
323
367
  return result.unsupportedAuth ? null : result.authorizerName;
324
368
  }
325
369
 
@@ -334,11 +378,24 @@ class HttpServer {
334
378
  return null;
335
379
  }
336
380
 
337
- (0, _serverlessLog.default)(`Configuring Authorization: ${path} ${authFunctionName}`);
381
+ if (this.log) {
382
+ this.log.notice(`Configuring Authorization: ${path} ${authFunctionName}`);
383
+ } else {
384
+ (0, _serverlessLog.default)(`Configuring Authorization: ${path} ${authFunctionName}`);
385
+ }
338
386
 
339
387
  const authFunction = _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.getFunction(authFunctionName);
340
388
 
341
- if (!authFunction) return (0, _serverlessLog.default)(`WARNING: Authorization function ${authFunctionName} does not exist`);
389
+ if (!authFunction) {
390
+ if (this.log) {
391
+ this.log.error(`Authorization function ${authFunctionName} does not exist`);
392
+ } else {
393
+ (0, _serverlessLog.default)(`WARNING: Authorization function ${authFunctionName} does not exist`);
394
+ }
395
+
396
+ return null;
397
+ }
398
+
342
399
  const authorizerOptions = {
343
400
  identitySource: 'method.request.header.Authorization',
344
401
  identityValidationExpression: '(.*)',
@@ -357,9 +414,14 @@ class HttpServer {
357
414
  const authSchemeName = `scheme-${authKey}`;
358
415
  const authStrategyName = `strategy-${authKey}`; // set strategy name for the route config
359
416
 
360
- (0, _debugLog.default)(`Creating Authorization scheme for ${authKey}`); // Create the Auth Scheme for the endpoint
417
+ if (this.log) {
418
+ this.log.debug(`Creating Authorization scheme for ${authKey}`);
419
+ } else {
420
+ (0, _debugLog.default)(`Creating Authorization scheme for ${authKey}`);
421
+ } // Create the Auth Scheme for the endpoint
422
+
361
423
 
362
- const scheme = (0, _createAuthScheme.default)(authorizerOptions, _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider, _classPrivateFieldLooseBase(this, _lambda)[_lambda]); // Set the auth scheme and strategy on the server
424
+ const scheme = (0, _createAuthScheme.default)(authorizerOptions, _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider, _classPrivateFieldLooseBase(this, _lambda)[_lambda], this); // Set the auth scheme and strategy on the server
363
425
 
364
426
  _classPrivateFieldLooseBase(this, _server)[_server].auth.scheme(authSchemeName, scheme);
365
427
 
@@ -368,6 +430,36 @@ class HttpServer {
368
430
  return authStrategyName;
369
431
  }
370
432
 
433
+ _setAuthorizationStrategy(endpoint, functionKey, method, path) {
434
+ var _customizations$offli;
435
+
436
+ /*
437
+ * The authentication strategy can be provided outside of this project
438
+ * by injecting the provider through a custom variable in the serverless.yml.
439
+ *
440
+ * see the example in the tests for more details
441
+ * /tests/integration/custom-authentication
442
+ */
443
+ const customizations = _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.custom;
444
+
445
+ if (customizations && (_customizations$offli = customizations.offline) !== null && _customizations$offli !== void 0 && _customizations$offli.customAuthenticationProvider) {
446
+ const root = pathUtils.resolve(_classPrivateFieldLooseBase(this, _serverless)[_serverless].serviceDir, 'require-resolver');
447
+ const customRequire = (0, _module.createRequire)(root);
448
+ const provider = customRequire(customizations.offline.customAuthenticationProvider);
449
+ const strategy = provider(endpoint, functionKey, method, path);
450
+
451
+ _classPrivateFieldLooseBase(this, _server)[_server].auth.scheme(strategy.scheme, strategy.getAuthenticateFunction);
452
+
453
+ _classPrivateFieldLooseBase(this, _server)[_server].auth.strategy(strategy.name, strategy.scheme);
454
+
455
+ return strategy.name;
456
+ } // If the endpoint has an authorization function, create an authStrategy for the route
457
+
458
+
459
+ const authStrategyName = _classPrivateFieldLooseBase(this, _options)[_options].noAuth ? null : this._configureJWTAuthorization(endpoint, functionKey, method, path) || this._configureAuthorization(endpoint, functionKey, method, path);
460
+ return authStrategyName;
461
+ }
462
+
371
463
  createRoutes(functionKey, httpEvent, handler) {
372
464
  const [handlerPath] = (0, _index2.splitHandlerPathAndName)(handler);
373
465
  let method;
@@ -395,7 +487,7 @@ class HttpServer {
395
487
  hapiPath = (0, _index2.generateHapiPath)(path, _classPrivateFieldLooseBase(this, _options)[_options], _classPrivateFieldLooseBase(this, _serverless)[_serverless]);
396
488
  }
397
489
 
398
- const endpoint = new _Endpoint.default((0, _path.join)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].config.servicePath, handlerPath), httpEvent);
490
+ const endpoint = new _Endpoint.default((0, pathUtils.join)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].config.servicePath, handlerPath), httpEvent, this.v3Utils);
399
491
  const stage = endpoint.isHttpApi ? '$default' : _classPrivateFieldLooseBase(this, _options)[_options].stage || _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.stage;
400
492
  const protectedRoutes = [];
401
493
 
@@ -417,10 +509,10 @@ class HttpServer {
417
509
  server,
418
510
  stage: endpoint.isHttpApi || _classPrivateFieldLooseBase(this, _options)[_options].noPrependStageInUrl ? null : stage,
419
511
  invokePath: `/2015-03-31/functions/${functionKey}/invocations`
420
- }); // If the endpoint has an authorization function, create an authStrategy for the route
512
+ });
421
513
 
514
+ const authStrategyName = this._setAuthorizationStrategy(endpoint, functionKey, method, path);
422
515
 
423
- const authStrategyName = _classPrivateFieldLooseBase(this, _options)[_options].noAuth ? null : this._configureJWTAuthorization(endpoint, functionKey, method, path) || this._configureAuthorization(endpoint, functionKey, method, path);
424
516
  let cors = null;
425
517
 
426
518
  if (endpoint.cors) {
@@ -431,7 +523,7 @@ class HttpServer {
431
523
  origin: endpoint.cors.origins || _classPrivateFieldLooseBase(this, _options)[_options].corsConfig.origin
432
524
  };
433
525
  } else if (_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi && _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi.cors) {
434
- const httpApiCors = (0, _index2.getHttpApiCorsConfig)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi.cors);
526
+ const httpApiCors = (0, _index2.getHttpApiCorsConfig)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.provider.httpApi.cors, this);
435
527
  cors = {
436
528
  origin: httpApiCors.allowedOrigins || [],
437
529
  credentials: httpApiCors.allowCredentials,
@@ -460,7 +552,12 @@ class HttpServer {
460
552
  // for more details, check https://github.com/dherault/serverless-offline/issues/204
461
553
 
462
554
  if (hapiMethod === 'HEAD') {
463
- (0, _serverlessLog.default)('HEAD method event detected. Skipping HAPI server route mapping ...');
555
+ if (this.log) {
556
+ this.log.notice('HEAD method event detected. Skipping HAPI server route mapping');
557
+ } else {
558
+ (0, _serverlessLog.default)('HEAD method event detected. Skipping HAPI server route mapping ...');
559
+ }
560
+
464
561
  return;
465
562
  }
466
563
 
@@ -473,6 +570,12 @@ class HttpServer {
473
570
  };
474
571
  }
475
572
 
573
+ const additionalRequestContext = {};
574
+
575
+ if (httpEvent.operationId) {
576
+ additionalRequestContext.operationName = httpEvent.operationId;
577
+ }
578
+
476
579
  hapiOptions.tags = ['api'];
477
580
 
478
581
  const hapiHandler = async (request, h) => {
@@ -499,7 +602,13 @@ class HttpServer {
499
602
 
500
603
  this._printBlankLine();
501
604
 
502
- (0, _serverlessLog.default)(`${method} ${request.path} (λ: ${functionKey})`); // Check for APIKey
605
+ if (this.log) {
606
+ this.log.notice();
607
+ this.log.notice(`${method} ${request.path} (λ: ${functionKey})`);
608
+ } else {
609
+ (0, _serverlessLog.default)(`${method} ${request.path} (λ: ${functionKey})`);
610
+ } // Check for APIKey
611
+
503
612
 
504
613
  if ((protectedRoutes.includes(`${hapiMethod}#${hapiPath}`) || protectedRoutes.includes(`ANY#${hapiPath}`)) && !_classPrivateFieldLooseBase(this, _options)[_options].noAuth) {
505
614
  const errorResponse = () => h.response({
@@ -523,7 +632,12 @@ class HttpServer {
523
632
  return errorResponse();
524
633
  }
525
634
  } else {
526
- (0, _debugLog.default)(`Missing x-api-key on private function ${functionKey}`);
635
+ if (this.log) {
636
+ this.log.debug(`Missing x-api-key on private function ${functionKey}`);
637
+ } else {
638
+ (0, _debugLog.default)(`Missing x-api-key on private function ${functionKey}`);
639
+ }
640
+
527
641
  return errorResponse();
528
642
  }
529
643
  }
@@ -550,17 +664,32 @@ class HttpServer {
550
664
 
551
665
  request.payload = parse(request.payload);
552
666
  } catch (err) {
553
- (0, _debugLog.default)('error in converting request.payload to JSON:', err);
667
+ if (this.log) {
668
+ this.log.debug('error in converting request.payload to JSON:', err);
669
+ } else {
670
+ (0, _debugLog.default)('error in converting request.payload to JSON:', err);
671
+ }
554
672
  }
555
673
  }
556
674
 
557
- (0, _debugLog.default)('contentType:', contentType);
558
- (0, _debugLog.default)('requestTemplate:', requestTemplate);
559
- (0, _debugLog.default)('payload:', request.payload);
675
+ if (this.log) {
676
+ this.log.debug('contentType:', contentType);
677
+ this.log.debug('requestTemplate:', requestTemplate);
678
+ this.log.debug('payload:', request.payload);
679
+ } else {
680
+ (0, _debugLog.default)('contentType:', contentType);
681
+ (0, _debugLog.default)('requestTemplate:', requestTemplate);
682
+ (0, _debugLog.default)('payload:', request.payload);
683
+ }
560
684
  /* REQUEST PAYLOAD SCHEMA VALIDATION */
561
685
 
686
+
562
687
  if (schema) {
563
- (0, _debugLog.default)('schema:', schema);
688
+ if (this.log) {
689
+ this.log.debug('schema:', schema);
690
+ } else {
691
+ (0, _debugLog.default)('schema:', schema);
692
+ }
564
693
 
565
694
  try {
566
695
  _payloadSchemaValidator.default.validate(schema, request.payload);
@@ -576,8 +705,13 @@ class HttpServer {
576
705
  if (integration === 'AWS') {
577
706
  if (requestTemplate) {
578
707
  try {
579
- (0, _debugLog.default)('_____ REQUEST TEMPLATE PROCESSING _____');
580
- event = new _index.LambdaIntegrationEvent(request, stage, requestTemplate, requestPath).create();
708
+ if (this.log) {
709
+ this.log.debug('_____ REQUEST TEMPLATE PROCESSING _____');
710
+ } else {
711
+ (0, _debugLog.default)('_____ REQUEST TEMPLATE PROCESSING _____');
712
+ }
713
+
714
+ event = new _index.LambdaIntegrationEvent(request, stage, requestTemplate, requestPath, this.v3Utils).create();
581
715
  } catch (err) {
582
716
  return this._reply502(response, `Error while parsing template "${contentType}" for ${functionKey}`, err);
583
717
  }
@@ -586,11 +720,15 @@ class HttpServer {
586
720
  }
587
721
  } else if (integration === 'AWS_PROXY') {
588
722
  const stageVariables = _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.custom ? _classPrivateFieldLooseBase(this, _serverless)[_serverless].service.custom.stageVariables : null;
589
- const lambdaProxyIntegrationEvent = endpoint.isHttpApi && endpoint.payload === '2.0' ? new _LambdaProxyIntegrationEventV.default(request, stage, endpoint.routeKey, stageVariables) : new _index.LambdaProxyIntegrationEvent(request, stage, requestPath, stageVariables, endpoint.isHttpApi ? endpoint.routeKey : null);
723
+ const lambdaProxyIntegrationEvent = endpoint.isHttpApi && endpoint.payload === '2.0' ? new _LambdaProxyIntegrationEventV.default(request, stage, endpoint.routeKey, stageVariables, additionalRequestContext, this.v3Utils) : new _index.LambdaProxyIntegrationEvent(request, stage, requestPath, stageVariables, endpoint.isHttpApi ? endpoint.routeKey : null, additionalRequestContext, this.v3Utils);
590
724
  event = lambdaProxyIntegrationEvent.create();
591
725
  }
592
726
 
593
- (0, _debugLog.default)('event:', event);
727
+ if (this.log) {
728
+ this.log.debug('event:', event);
729
+ } else {
730
+ (0, _debugLog.default)('event:', event);
731
+ }
594
732
 
595
733
  const lambdaFunction = _classPrivateFieldLooseBase(this, _lambda)[_lambda].get(functionKey);
596
734
 
@@ -606,7 +744,12 @@ class HttpServer {
606
744
  // Everything in this block happens once the lambda function has resolved
607
745
 
608
746
 
609
- (0, _debugLog.default)('_____ HANDLER RESOLVED _____');
747
+ if (this.log) {
748
+ this.log.debug('_____ HANDLER RESOLVED _____');
749
+ } else {
750
+ (0, _debugLog.default)('_____ HANDLER RESOLVED _____');
751
+ }
752
+
610
753
  let responseName = 'default';
611
754
  const {
612
755
  contentHandling,
@@ -645,10 +788,19 @@ class HttpServer {
645
788
  errorType: err.constructor.name,
646
789
  stackTrace: this._getArrayStackTrace(err.stack)
647
790
  };
648
- (0, _serverlessLog.default)(`Failure: ${errorMessage}`);
791
+
792
+ if (this.log) {
793
+ this.log.error(errorMessage);
794
+ } else {
795
+ (0, _serverlessLog.default)(`Failure: ${errorMessage}`);
796
+ }
649
797
 
650
798
  if (!_classPrivateFieldLooseBase(this, _options)[_options].hideStackTraces) {
651
- console.error(err.stack);
799
+ if (this.log) {
800
+ this.log.error(err.stack);
801
+ } else {
802
+ console.error(err.stack);
803
+ }
652
804
  }
653
805
 
654
806
  for (const [key, value] of Object.entries(endpoint.responses)) {
@@ -659,7 +811,12 @@ class HttpServer {
659
811
  }
660
812
  }
661
813
 
662
- (0, _debugLog.default)(`Using response '${responseName}'`);
814
+ if (this.log) {
815
+ this.log.debug(`Using response '${responseName}'`);
816
+ } else {
817
+ (0, _debugLog.default)(`Using response '${responseName}'`);
818
+ }
819
+
663
820
  const chosenResponse = endpoint.responses[responseName];
664
821
  /* RESPONSE PARAMETERS PROCCESSING */
665
822
 
@@ -669,24 +826,46 @@ class HttpServer {
669
826
 
670
827
  if (responseParameters) {
671
828
  const responseParametersKeys = Object.keys(responseParameters);
672
- (0, _debugLog.default)('_____ RESPONSE PARAMETERS PROCCESSING _____');
673
- (0, _debugLog.default)(`Found ${responseParametersKeys.length} responseParameters for '${responseName}' response`); // responseParameters use the following shape: "key": "value"
829
+
830
+ if (this.log) {
831
+ this.log.debug('_____ RESPONSE PARAMETERS PROCCESSING _____');
832
+ this.log.debug(`Found ${responseParametersKeys.length} responseParameters for '${responseName}' response`);
833
+ } else {
834
+ (0, _debugLog.default)('_____ RESPONSE PARAMETERS PROCCESSING _____');
835
+ (0, _debugLog.default)();
836
+ } // responseParameters use the following shape: "key": "value"
837
+
674
838
 
675
839
  Object.entries(responseParameters).forEach(([key, value]) => {
676
840
  const keyArray = key.split('.'); // eg: "method.response.header.location"
677
841
 
678
842
  const valueArray = value.split('.'); // eg: "integration.response.body.redirect.url"
679
843
 
680
- (0, _debugLog.default)(`Processing responseParameter "${key}": "${value}"`); // For now the plugin only supports modifying headers
844
+ if (this.log) {
845
+ this.log.debug(`Processing responseParameter "${key}": "${value}"`);
846
+ } else {
847
+ (0, _debugLog.default)(`Processing responseParameter "${key}": "${value}"`);
848
+ } // For now the plugin only supports modifying headers
849
+
681
850
 
682
851
  if (key.startsWith('method.response.header') && keyArray[3]) {
683
852
  const headerName = keyArray.slice(3).join('.');
684
853
  let headerValue;
685
- (0, _debugLog.default)('Found header in left-hand:', headerName);
854
+
855
+ if (this.log) {
856
+ this.log.debug('Found header in left-hand:', headerName);
857
+ } else {
858
+ (0, _debugLog.default)('Found header in left-hand:', headerName);
859
+ }
686
860
 
687
861
  if (value.startsWith('integration.response')) {
688
862
  if (valueArray[2] === 'body') {
689
- (0, _debugLog.default)('Found body in right-hand');
863
+ if (this.log) {
864
+ this.log.debug('Found body in right-hand');
865
+ } else {
866
+ (0, _debugLog.default)('Found body in right-hand');
867
+ }
868
+
690
869
  headerValue = valueArray[3] ? (0, _index2.jsonPath)(result, valueArray.slice(3).join('.')) : result;
691
870
 
692
871
  if (typeof headerValue === 'undefined' || headerValue === null) {
@@ -697,8 +876,13 @@ class HttpServer {
697
876
  } else {
698
877
  this._printBlankLine();
699
878
 
700
- (0, _serverlessLog.default)(`Warning: while processing responseParameter "${key}": "${value}"`);
701
- (0, _serverlessLog.default)(`Offline plugin only supports "integration.response.body[.JSON_path]" right-hand responseParameter. Found "${value}" instead. Skipping.`);
879
+ if (this.log) {
880
+ this.log.warning();
881
+ this.log.warning(`Offline plugin only supports "integration.response.body[.JSON_path]" right-hand responseParameter. Found "${value}" (for "${key}"") instead. Skipping.`);
882
+ } else {
883
+ (0, _serverlessLog.default)(`Warning: while processing responseParameter "${key}": "${value}"`);
884
+ (0, _serverlessLog.default)(`Offline plugin only supports "integration.response.body[.JSON_path]" right-hand responseParameter. Found "${value}" instead. Skipping.`);
885
+ }
702
886
 
703
887
  this._logPluginIssue();
704
888
 
@@ -710,16 +894,30 @@ class HttpServer {
710
894
 
711
895
 
712
896
  if (headerValue === '') {
713
- (0, _serverlessLog.default)(`Warning: empty value for responseParameter "${key}": "${value}", it won't be set`);
897
+ if (this.log) {
898
+ this.log.warning(`Empty value for responseParameter "${key}": "${value}", it won't be set`);
899
+ } else {
900
+ (0, _serverlessLog.default)(`Warning: empty value for responseParameter "${key}": "${value}", it won't be set`);
901
+ }
714
902
  } else {
715
- (0, _debugLog.default)(`Will assign "${headerValue}" to header "${headerName}"`);
903
+ if (this.log) {
904
+ this.log.debug(`Will assign "${headerValue}" to header "${headerName}"`);
905
+ } else {
906
+ (0, _debugLog.default)(`Will assign "${headerValue}" to header "${headerName}"`);
907
+ }
908
+
716
909
  response.header(headerName, headerValue);
717
910
  }
718
911
  } else {
719
912
  this._printBlankLine();
720
913
 
721
- (0, _serverlessLog.default)(`Warning: while processing responseParameter "${key}": "${value}"`);
722
- (0, _serverlessLog.default)(`Offline plugin only supports "method.response.header.PARAM_NAME" left-hand responseParameter. Found "${key}" instead. Skipping.`);
914
+ if (this.log) {
915
+ this.log.warning();
916
+ this.log.warning(`Offline plugin only supports "method.response.header.PARAM_NAME" left-hand responseParameter. Found "${key}" instead. Skipping.`);
917
+ } else {
918
+ (0, _serverlessLog.default)(`Warning: while processing responseParameter "${key}": "${value}"`);
919
+ (0, _serverlessLog.default)(`Offline plugin only supports "method.response.header.PARAM_NAME" left-hand responseParameter. Found "${key}" instead. Skipping.`);
920
+ }
723
921
 
724
922
  this._logPluginIssue();
725
923
 
@@ -748,17 +946,26 @@ class HttpServer {
748
946
  const responseTemplate = responseTemplates[responseContentType];
749
947
 
750
948
  if (responseTemplate && responseTemplate !== '\n') {
751
- (0, _debugLog.default)('_____ RESPONSE TEMPLATE PROCCESSING _____');
752
- (0, _debugLog.default)(`Using responseTemplate '${responseContentType}'`);
949
+ if (this.log) {
950
+ this.log.debug('_____ RESPONSE TEMPLATE PROCCESSING _____');
951
+ this.log.debug(`Using responseTemplate '${responseContentType}'`);
952
+ } else {
953
+ (0, _debugLog.default)('_____ RESPONSE TEMPLATE PROCCESSING _____');
954
+ (0, _debugLog.default)(`Using responseTemplate '${responseContentType}'`);
955
+ }
753
956
 
754
957
  try {
755
958
  const reponseContext = new _index.VelocityContext(request, stage, result).getContext();
756
959
  result = (0, _index.renderVelocityTemplateObject)({
757
960
  root: responseTemplate
758
- }, reponseContext).root;
961
+ }, reponseContext, this.v3Utils).root;
759
962
  } catch (error) {
760
- (0, _serverlessLog.default)(`Error while parsing responseTemplate '${responseContentType}' for lambda ${functionKey}:`);
761
- console.log(error.stack);
963
+ if (this.log) {
964
+ this.log.error(`Error while parsing responseTemplate '${responseContentType}' for lambda ${functionKey}:\n${error.stack}`);
965
+ } else {
966
+ (0, _serverlessLog.default)(`Error while parsing responseTemplate '${responseContentType}' for lambda ${functionKey}:`);
967
+ console.log(error.stack);
968
+ }
762
969
  }
763
970
  }
764
971
  }
@@ -775,7 +982,12 @@ class HttpServer {
775
982
  if (!chosenResponse.statusCode) {
776
983
  this._printBlankLine();
777
984
 
778
- (0, _serverlessLog.default)(`Warning: No statusCode found for response "${responseName}".`);
985
+ if (this.log) {
986
+ this.log.warning();
987
+ this.log.warning(`No statusCode found for response "${responseName}".`);
988
+ } else {
989
+ (0, _serverlessLog.default)(`Warning: No statusCode found for response "${responseName}".`);
990
+ }
779
991
  }
780
992
 
781
993
  response.header('Content-Type', responseContentType, {
@@ -830,7 +1042,11 @@ class HttpServer {
830
1042
  });
831
1043
  }
832
1044
 
833
- (0, _debugLog.default)('headers', headers);
1045
+ if (this.log) {
1046
+ this.log.debug('headers', headers);
1047
+ } else {
1048
+ (0, _debugLog.default)('headers', headers);
1049
+ }
834
1050
 
835
1051
  const parseCookies = headerValue => {
836
1052
  const cookieName = headerValue.slice(0, headerValue.indexOf('='));
@@ -888,7 +1104,13 @@ class HttpServer {
888
1104
  whatToLog = stringify(result);
889
1105
  } catch (error) {// nothing
890
1106
  } finally {
891
- if (_classPrivateFieldLooseBase(this, _options)[_options].printOutput) (0, _serverlessLog.default)(err ? `Replying ${statusCode}` : `[${statusCode}] ${whatToLog}`);
1107
+ if (_classPrivateFieldLooseBase(this, _options)[_options].printOutput) {
1108
+ if (this.log) {
1109
+ this.log.notice(err ? `Replying ${statusCode}` : `[${statusCode}] ${whatToLog}`);
1110
+ } else {
1111
+ (0, _serverlessLog.default)(err ? `Replying ${statusCode}` : `[${statusCode}] ${whatToLog}`);
1112
+ }
1113
+ }
892
1114
  } // Bon voyage!
893
1115
 
894
1116
 
@@ -905,7 +1127,13 @@ class HttpServer {
905
1127
 
906
1128
  _replyError(statusCode, response, message, error) {
907
1129
  (0, _serverlessLog.default)(message);
908
- console.error(error);
1130
+
1131
+ if (this.log) {
1132
+ this.log.error(error);
1133
+ } else {
1134
+ console.error(error);
1135
+ }
1136
+
909
1137
  response.header('Content-Type', 'application/json');
910
1138
  response.statusCode = statusCode;
911
1139
  response.source = {
@@ -942,7 +1170,13 @@ class HttpServer {
942
1170
 
943
1171
  this._printBlankLine();
944
1172
 
945
- (0, _serverlessLog.default)('Routes defined in resources:');
1173
+ if (this.log) {
1174
+ this.log.notice();
1175
+ this.log.notice('Routes defined in resources:');
1176
+ } else {
1177
+ (0, _serverlessLog.default)('Routes defined in resources:');
1178
+ }
1179
+
946
1180
  Object.entries(resourceRoutes).forEach(([methodId, resourceRoutesObj]) => {
947
1181
  const {
948
1182
  isProxy,
@@ -952,12 +1186,22 @@ class HttpServer {
952
1186
  } = resourceRoutesObj;
953
1187
 
954
1188
  if (!isProxy) {
955
- (0, _serverlessLog.default)(`WARNING: Only HTTP_PROXY is supported. Path '${pathResource}' is ignored.`);
1189
+ if (this.log) {
1190
+ this.log.warning(`Only HTTP_PROXY is supported. Path '${pathResource}' is ignored.`);
1191
+ } else {
1192
+ (0, _serverlessLog.default)(`WARNING: Only HTTP_PROXY is supported. Path '${pathResource}' is ignored.`);
1193
+ }
1194
+
956
1195
  return;
957
1196
  }
958
1197
 
959
1198
  if (!pathResource) {
960
- (0, _serverlessLog.default)(`WARNING: Could not resolve path for '${methodId}'.`);
1199
+ if (this.log) {
1200
+ this.log.warning(`Could not resolve path for '${methodId}'.`);
1201
+ } else {
1202
+ (0, _serverlessLog.default)(`WARNING: Could not resolve path for '${methodId}'.`);
1203
+ }
1204
+
961
1205
  return;
962
1206
  }
963
1207
 
@@ -966,7 +1210,12 @@ class HttpServer {
966
1210
  const proxyUriInUse = proxyUriOverwrite.Uri || proxyUri;
967
1211
 
968
1212
  if (!proxyUriInUse) {
969
- (0, _serverlessLog.default)(`WARNING: Could not load Proxy Uri for '${methodId}'`);
1213
+ if (this.log) {
1214
+ this.log.warning(`Could not load Proxy Uri for '${methodId}'`);
1215
+ } else {
1216
+ (0, _serverlessLog.default)(`WARNING: Could not load Proxy Uri for '${methodId}'`);
1217
+ }
1218
+
970
1219
  return;
971
1220
  }
972
1221
 
@@ -985,7 +1234,12 @@ class HttpServer {
985
1234
  // for more details, check https://github.com/dherault/serverless-offline/issues/204
986
1235
 
987
1236
  if (hapiMethod === 'HEAD') {
988
- (0, _serverlessLog.default)('HEAD method event detected. Skipping HAPI server route mapping ...');
1237
+ if (this.log) {
1238
+ this.log.notice('HEAD method event detected. Skipping HAPI server route mapping');
1239
+ } else {
1240
+ (0, _serverlessLog.default)('HEAD method event detected. Skipping HAPI server route mapping ...');
1241
+ }
1242
+
989
1243
  return;
990
1244
  }
991
1245
 
@@ -995,8 +1249,16 @@ class HttpServer {
995
1249
  };
996
1250
  }
997
1251
 
998
- (0, _serverlessLog.default)(`${method} ${hapiPath} -> ${proxyUriInUse}`); // hapiOptions.tags = ['api']
1252
+ if (this.log) {
1253
+ this.log.notice(`${method} ${hapiPath} -> ${proxyUriInUse}`);
1254
+ } else {
1255
+ (0, _serverlessLog.default)(`${method} ${hapiPath} -> ${proxyUriInUse}`);
1256
+ } // hapiOptions.tags = ['api']
1257
+
999
1258
 
1259
+ const {
1260
+ log
1261
+ } = this;
1000
1262
  const route = {
1001
1263
  handler(request, h) {
1002
1264
  const {
@@ -1011,7 +1273,12 @@ class HttpServer {
1011
1273
  resultUri += request.url.search; // search is empty string by default
1012
1274
  }
1013
1275
 
1014
- (0, _serverlessLog.default)(`PROXY ${request.method} ${request.url.pathname} -> ${resultUri}`);
1276
+ if (log) {
1277
+ log.notice(`PROXY ${request.method} ${request.url.pathname} -> ${resultUri}`);
1278
+ } else {
1279
+ (0, _serverlessLog.default)(`PROXY ${request.method} ${request.url.pathname} -> ${resultUri}`);
1280
+ }
1281
+
1015
1282
  return h.proxy({
1016
1283
  passThrough: true,
1017
1284
  uri: resultUri
@@ -1068,9 +1335,15 @@ class HttpServer {
1068
1335
 
1069
1336
  _injectLastRequest() {
1070
1337
  if (_classPrivateFieldLooseBase(this, _lastRequestOptions)[_lastRequestOptions]) {
1071
- (0, _serverlessLog.default)('Replaying HTTP last request');
1338
+ if (this.log) {
1339
+ this.log.notice('Replaying HTTP last request');
1072
1340
 
1073
- _classPrivateFieldLooseBase(this, _server)[_server].inject(_classPrivateFieldLooseBase(this, _lastRequestOptions)[_lastRequestOptions]);
1341
+ _classPrivateFieldLooseBase(this, _server)[_server].inject(_classPrivateFieldLooseBase(this, _lastRequestOptions)[_lastRequestOptions]);
1342
+ } else {
1343
+ (0, _serverlessLog.default)('Replaying HTTP last request');
1344
+ }
1345
+ } else if (this.log) {
1346
+ this.log.notice('No last HTTP request to replay!');
1074
1347
  } else {
1075
1348
  (0, _serverlessLog.default)('No last HTTP request to replay!');
1076
1349
  }