serverless-offline 8.5.0 → 8.8.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 +118 -77
- package/dist/ServerlessOffline.js +27 -8
- package/dist/config/supportedRuntimes.js +1 -1
- package/dist/debugLog.js +3 -1
- 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/authValidateContext.js +53 -0
- package/dist/events/http/Endpoint.js +3 -1
- package/dist/events/http/HttpServer.js +28 -21
- package/dist/events/http/OfflineEndpoint.js +23 -25
- package/dist/events/http/createAuthScheme.js +23 -12
- package/dist/events/http/createJWTAuthScheme.js +6 -2
- package/dist/events/http/lambda-events/LambdaIntegrationEvent.js +26 -0
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEvent.js +16 -14
- package/dist/events/http/lambda-events/LambdaProxyIntegrationEventV2.js +22 -12
- package/dist/events/http/lambda-events/VelocityContext.js +3 -1
- package/dist/events/http/lambda-events/renderVelocityTemplateObject.js +4 -1
- package/dist/events/schedule/Schedule.js +10 -9
- package/dist/events/websocket/HttpServer.js +3 -1
- package/dist/events/websocket/WebSocketClients.js +224 -5
- package/dist/events/websocket/WebSocketServer.js +5 -6
- package/dist/events/websocket/lambda-events/WebSocketAuthorizerEvent.js +99 -0
- package/dist/events/websocket/lambda-events/index.js +8 -0
- package/dist/index.js +0 -4
- package/dist/lambda/HttpServer.js +3 -1
- package/dist/lambda/Lambda.js +5 -1
- package/dist/lambda/LambdaFunction.js +1 -1
- package/dist/lambda/handler-runner/HandlerRunner.js +0 -27
- package/dist/lambda/handler-runner/child-process-runner/childProcessHelper.js +15 -6
- package/dist/lambda/handler-runner/docker-runner/DockerContainer.js +6 -5
- package/dist/lambda/handler-runner/go-runner/GoRunner.js +34 -15
- package/dist/lambda/handler-runner/in-process-runner/InProcessRunner.js +23 -14
- package/dist/lambda/handler-runner/java-runner/JavaRunner.js +4 -3
- package/dist/lambda/handler-runner/python-runner/PythonRunner.js +15 -10
- package/dist/lambda/handler-runner/ruby-runner/RubyRunner.js +3 -6
- package/dist/lambda/handler-runner/worker-thread-runner/workerThreadHelper.js +3 -1
- package/dist/utils/generateHapiPath.js +1 -1
- package/dist/utils/getHttpApiCorsConfig.js +4 -8
- package/dist/utils/index.js +11 -4
- package/dist/utils/lowerCaseKeys.js +14 -0
- package/dist/utils/resolveJoins.js +4 -2
- package/package.json +26 -29
- package/dist/checkEngine.js +0 -21
|
@@ -11,13 +11,15 @@ var _fs = require("fs");
|
|
|
11
11
|
|
|
12
12
|
var pathUtils = _interopRequireWildcard(require("path"));
|
|
13
13
|
|
|
14
|
+
var _process = _interopRequireWildcard(require("process"));
|
|
15
|
+
|
|
14
16
|
var _h2o = _interopRequireDefault(require("@hapi/h2o2"));
|
|
15
17
|
|
|
16
18
|
var _hapi = require("@hapi/hapi");
|
|
17
19
|
|
|
18
20
|
var _module = require("module");
|
|
19
21
|
|
|
20
|
-
var _authFunctionNameExtractor = _interopRequireDefault(require("
|
|
22
|
+
var _authFunctionNameExtractor = _interopRequireDefault(require("../authFunctionNameExtractor.js"));
|
|
21
23
|
|
|
22
24
|
var _authJWTSettingsExtractor = _interopRequireDefault(require("./authJWTSettingsExtractor.js"));
|
|
23
25
|
|
|
@@ -57,6 +59,11 @@ const {
|
|
|
57
59
|
parse,
|
|
58
60
|
stringify
|
|
59
61
|
} = JSON;
|
|
62
|
+
const {
|
|
63
|
+
assign,
|
|
64
|
+
entries,
|
|
65
|
+
keys
|
|
66
|
+
} = Object;
|
|
60
67
|
|
|
61
68
|
var _lambda = /*#__PURE__*/_classPrivateFieldLooseKey("lambda");
|
|
62
69
|
|
|
@@ -208,7 +215,7 @@ class HttpServer {
|
|
|
208
215
|
} // Override default headers with headers that have been explicitly set
|
|
209
216
|
|
|
210
217
|
|
|
211
|
-
|
|
218
|
+
keys(explicitlySetHeaders).forEach(key => {
|
|
212
219
|
const value = explicitlySetHeaders[key];
|
|
213
220
|
|
|
214
221
|
if (value) {
|
|
@@ -238,7 +245,7 @@ class HttpServer {
|
|
|
238
245
|
console.error(`Unexpected error while starting serverless-offline server on port ${httpPort}:`, err);
|
|
239
246
|
}
|
|
240
247
|
|
|
241
|
-
|
|
248
|
+
(0, _process.exit)(1);
|
|
242
249
|
} // TODO move the following block
|
|
243
250
|
|
|
244
251
|
|
|
@@ -257,8 +264,8 @@ class HttpServer {
|
|
|
257
264
|
(0, _serverlessLog.default)('Enter "rp" to replay the last request');
|
|
258
265
|
}
|
|
259
266
|
|
|
260
|
-
if (
|
|
261
|
-
|
|
267
|
+
if (_process.env.NODE_ENV !== 'test') {
|
|
268
|
+
_process.default.openStdin().addListener('data', data => {
|
|
262
269
|
// note: data is an object, and when converted to a string it will
|
|
263
270
|
// end with a linefeed. so we (rather crudely) account for that
|
|
264
271
|
// with toString() and then trim()
|
|
@@ -293,7 +300,7 @@ class HttpServer {
|
|
|
293
300
|
|
|
294
301
|
|
|
295
302
|
_printBlankLine() {
|
|
296
|
-
if (
|
|
303
|
+
if (_process.env.NODE_ENV !== 'test') {
|
|
297
304
|
if (this.log) {
|
|
298
305
|
this.log.notice();
|
|
299
306
|
} else {
|
|
@@ -405,7 +412,7 @@ class HttpServer {
|
|
|
405
412
|
if (typeof endpoint.authorizer === 'string') {
|
|
406
413
|
authorizerOptions.name = authFunctionName;
|
|
407
414
|
} else {
|
|
408
|
-
|
|
415
|
+
assign(authorizerOptions, endpoint.authorizer);
|
|
409
416
|
} // Create a unique scheme per endpoint
|
|
410
417
|
// This allows the methodArn on the event property to be set appropriately
|
|
411
418
|
|
|
@@ -803,7 +810,7 @@ class HttpServer {
|
|
|
803
810
|
}
|
|
804
811
|
}
|
|
805
812
|
|
|
806
|
-
for (const [key, value] of
|
|
813
|
+
for (const [key, value] of entries(endpoint.responses)) {
|
|
807
814
|
if (key !== 'default' && errorMessage.match(`^${value.selectionPattern || key}$`)) {
|
|
808
815
|
responseName = key;
|
|
809
816
|
break;
|
|
@@ -825,7 +832,7 @@ class HttpServer {
|
|
|
825
832
|
} = chosenResponse;
|
|
826
833
|
|
|
827
834
|
if (responseParameters) {
|
|
828
|
-
const responseParametersKeys =
|
|
835
|
+
const responseParametersKeys = keys(responseParameters);
|
|
829
836
|
|
|
830
837
|
if (this.log) {
|
|
831
838
|
this.log.debug('_____ RESPONSE PARAMETERS PROCCESSING _____');
|
|
@@ -836,7 +843,7 @@ class HttpServer {
|
|
|
836
843
|
} // responseParameters use the following shape: "key": "value"
|
|
837
844
|
|
|
838
845
|
|
|
839
|
-
|
|
846
|
+
entries(responseParameters).forEach(([key, value]) => {
|
|
840
847
|
const keyArray = key.split('.'); // eg: "method.response.header.location"
|
|
841
848
|
|
|
842
849
|
const valueArray = value.split('.'); // eg: "integration.response.body.redirect.url"
|
|
@@ -930,7 +937,7 @@ class HttpServer {
|
|
|
930
937
|
|
|
931
938
|
if (integration === 'AWS') {
|
|
932
939
|
const endpointResponseHeaders = endpoint.response && endpoint.response.headers || {};
|
|
933
|
-
|
|
940
|
+
entries(endpointResponseHeaders).filter(([, value]) => typeof value === 'string' && /^'.*?'$/.test(value)).forEach(([key, value]) => response.header(key, value.slice(1, -1)));
|
|
934
941
|
/* LAMBDA INTEGRATION RESPONSE TEMPLATE PROCCESSING */
|
|
935
942
|
// If there is a responseTemplate, we apply it to the result
|
|
936
943
|
|
|
@@ -939,7 +946,7 @@ class HttpServer {
|
|
|
939
946
|
} = chosenResponse;
|
|
940
947
|
|
|
941
948
|
if (typeof responseTemplates === 'object') {
|
|
942
|
-
const responseTemplatesKeys =
|
|
949
|
+
const responseTemplatesKeys = keys(responseTemplates);
|
|
943
950
|
|
|
944
951
|
if (responseTemplatesKeys.length) {
|
|
945
952
|
// BAD IMPLEMENTATION: first key in responseTemplates
|
|
@@ -1001,7 +1008,7 @@ class HttpServer {
|
|
|
1001
1008
|
response.source = _buffer.Buffer.from(result, 'base64');
|
|
1002
1009
|
response.variety = 'buffer';
|
|
1003
1010
|
} else if (typeof result === 'string') {
|
|
1004
|
-
response.source =
|
|
1011
|
+
response.source = stringify(result);
|
|
1005
1012
|
} else if (result && result.body && typeof result.body !== 'string') {
|
|
1006
1013
|
return this._reply502(response, 'According to the API Gateway specs, the body content must be stringified. Check your Lambda response and make sure you are invoking JSON.stringify(YOUR_CONTENT) on your body object', {});
|
|
1007
1014
|
} else {
|
|
@@ -1010,7 +1017,7 @@ class HttpServer {
|
|
|
1010
1017
|
} else if (integration === 'AWS_PROXY') {
|
|
1011
1018
|
/* LAMBDA PROXY INTEGRATION HAPIJS RESPONSE CONFIGURATION */
|
|
1012
1019
|
if (endpoint.isHttpApi && endpoint.payload === '2.0' && (typeof result === 'string' || !result.statusCode)) {
|
|
1013
|
-
const body = typeof result === 'string' ? result :
|
|
1020
|
+
const body = typeof result === 'string' ? result : stringify(result);
|
|
1014
1021
|
result = {
|
|
1015
1022
|
isBase64Encoded: false,
|
|
1016
1023
|
statusCode: 200,
|
|
@@ -1031,13 +1038,13 @@ class HttpServer {
|
|
|
1031
1038
|
const headers = {};
|
|
1032
1039
|
|
|
1033
1040
|
if (result && result.headers) {
|
|
1034
|
-
|
|
1041
|
+
keys(result.headers).forEach(header => {
|
|
1035
1042
|
headers[header] = (headers[header] || []).concat(result.headers[header]);
|
|
1036
1043
|
});
|
|
1037
1044
|
}
|
|
1038
1045
|
|
|
1039
1046
|
if (result && result.multiValueHeaders) {
|
|
1040
|
-
|
|
1047
|
+
keys(result.multiValueHeaders).forEach(header => {
|
|
1041
1048
|
headers[header] = (headers[header] || []).concat(result.multiValueHeaders[header]);
|
|
1042
1049
|
});
|
|
1043
1050
|
}
|
|
@@ -1057,7 +1064,7 @@ class HttpServer {
|
|
|
1057
1064
|
});
|
|
1058
1065
|
};
|
|
1059
1066
|
|
|
1060
|
-
|
|
1067
|
+
keys(headers).forEach(header => {
|
|
1061
1068
|
if (header.toLowerCase() === 'set-cookie') {
|
|
1062
1069
|
headers[header].forEach(parseCookies);
|
|
1063
1070
|
} else {
|
|
@@ -1081,7 +1088,7 @@ class HttpServer {
|
|
|
1081
1088
|
});
|
|
1082
1089
|
|
|
1083
1090
|
if (typeof result === 'string') {
|
|
1084
|
-
response.source =
|
|
1091
|
+
response.source = stringify(result);
|
|
1085
1092
|
} else if (result && typeof result.body !== 'undefined') {
|
|
1086
1093
|
if (result.isBase64Encoded) {
|
|
1087
1094
|
response.encoding = 'binary';
|
|
@@ -1164,7 +1171,7 @@ class HttpServer {
|
|
|
1164
1171
|
|
|
1165
1172
|
const resourceRoutes = (0, _parseResources.default)(_classPrivateFieldLooseBase(this, _serverless)[_serverless].service.resources);
|
|
1166
1173
|
|
|
1167
|
-
if (!resourceRoutes || !
|
|
1174
|
+
if (!resourceRoutes || !keys(resourceRoutes).length) {
|
|
1168
1175
|
return;
|
|
1169
1176
|
}
|
|
1170
1177
|
|
|
@@ -1177,7 +1184,7 @@ class HttpServer {
|
|
|
1177
1184
|
(0, _serverlessLog.default)('Routes defined in resources:');
|
|
1178
1185
|
}
|
|
1179
1186
|
|
|
1180
|
-
|
|
1187
|
+
entries(resourceRoutes).forEach(([methodId, resourceRoutesObj]) => {
|
|
1181
1188
|
const {
|
|
1182
1189
|
isProxy,
|
|
1183
1190
|
method,
|
|
@@ -1265,7 +1272,7 @@ class HttpServer {
|
|
|
1265
1272
|
params
|
|
1266
1273
|
} = request;
|
|
1267
1274
|
let resultUri = proxyUriInUse;
|
|
1268
|
-
|
|
1275
|
+
entries(params).forEach(([key, value]) => {
|
|
1269
1276
|
resultUri = resultUri.replace(`{${key}}`, value);
|
|
1270
1277
|
});
|
|
1271
1278
|
|
|
@@ -7,32 +7,30 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
class OfflineEndpoint {
|
|
9
9
|
constructor() {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
'application/json': ''
|
|
18
|
-
},
|
|
19
|
-
responses: {
|
|
20
|
-
default: {
|
|
21
|
-
400: {
|
|
22
|
-
statusCode: '400'
|
|
23
|
-
},
|
|
24
|
-
responseModels: {
|
|
25
|
-
'application/json;charset=UTF-8': 'Empty'
|
|
26
|
-
},
|
|
27
|
-
responseParameters: {},
|
|
28
|
-
responseTemplates: {
|
|
29
|
-
'application/json;charset=UTF-8': ''
|
|
30
|
-
},
|
|
31
|
-
statusCode: 200
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
type: 'AWS'
|
|
10
|
+
this.apiKeyRequired = false;
|
|
11
|
+
this.authorizationType = 'none';
|
|
12
|
+
this.authorizerFunction = false;
|
|
13
|
+
this.path = '';
|
|
14
|
+
this.requestParameters = {};
|
|
15
|
+
this.requestTemplates = {
|
|
16
|
+
'application/json': ''
|
|
35
17
|
};
|
|
18
|
+
this.responses = {
|
|
19
|
+
default: {
|
|
20
|
+
400: {
|
|
21
|
+
statusCode: '400'
|
|
22
|
+
},
|
|
23
|
+
responseModels: {
|
|
24
|
+
'application/json;charset=UTF-8': 'Empty'
|
|
25
|
+
},
|
|
26
|
+
responseParameters: {},
|
|
27
|
+
responseTemplates: {
|
|
28
|
+
'application/json;charset=UTF-8': ''
|
|
29
|
+
},
|
|
30
|
+
statusCode: 200
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
this.type = 'AWS';
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
}
|
|
@@ -7,7 +7,9 @@ exports.default = createAuthScheme;
|
|
|
7
7
|
|
|
8
8
|
var _boom = _interopRequireDefault(require("@hapi/boom"));
|
|
9
9
|
|
|
10
|
-
var _authCanExecuteResource = _interopRequireDefault(require("
|
|
10
|
+
var _authCanExecuteResource = _interopRequireDefault(require("../authCanExecuteResource.js"));
|
|
11
|
+
|
|
12
|
+
var _authValidateContext = _interopRequireDefault(require("../authValidateContext.js"));
|
|
11
13
|
|
|
12
14
|
var _debugLog = _interopRequireDefault(require("../../debugLog.js"));
|
|
13
15
|
|
|
@@ -113,11 +115,9 @@ function createAuthScheme(authorizerOptions, provider, lambda, {
|
|
|
113
115
|
|
|
114
116
|
try {
|
|
115
117
|
const result = await lambdaFunction.runHandler();
|
|
116
|
-
if (result === 'Unauthorized') return _boom.default.unauthorized('Unauthorized'); //
|
|
117
|
-
|
|
118
|
-
const policy = result; // Validate that the policy document has the principalId set
|
|
118
|
+
if (result === 'Unauthorized') return _boom.default.unauthorized('Unauthorized'); // Validate that the policy document has the principalId set
|
|
119
119
|
|
|
120
|
-
if (!
|
|
120
|
+
if (!result.principalId) {
|
|
121
121
|
if (log) {
|
|
122
122
|
log.notice(`Authorization response did not include a principalId: (λ: ${authFunName})`);
|
|
123
123
|
} else {
|
|
@@ -127,7 +127,7 @@ function createAuthScheme(authorizerOptions, provider, lambda, {
|
|
|
127
127
|
return _boom.default.forbidden('No principalId set on the Response');
|
|
128
128
|
}
|
|
129
129
|
|
|
130
|
-
if (!(0, _authCanExecuteResource.default)(
|
|
130
|
+
if (!(0, _authCanExecuteResource.default)(result.policyDocument, event.methodArn)) {
|
|
131
131
|
if (log) {
|
|
132
132
|
log.notice(`Authorization response didn't authorize user to access resource: (λ: ${authFunName})`);
|
|
133
133
|
} else {
|
|
@@ -135,6 +135,18 @@ function createAuthScheme(authorizerOptions, provider, lambda, {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
return _boom.default.forbidden('User is not authorized to access this resource');
|
|
138
|
+
} // validate the resulting context, ensuring that all
|
|
139
|
+
// values are either string, number, or boolean types
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if (result.context) {
|
|
143
|
+
const validationResult = (0, _authValidateContext.default)(result.context, authFunName);
|
|
144
|
+
|
|
145
|
+
if (validationResult instanceof Error) {
|
|
146
|
+
return validationResult;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
result.context = validationResult;
|
|
138
150
|
}
|
|
139
151
|
|
|
140
152
|
if (log) {
|
|
@@ -145,17 +157,16 @@ function createAuthScheme(authorizerOptions, provider, lambda, {
|
|
|
145
157
|
|
|
146
158
|
const authorizer = {
|
|
147
159
|
integrationLatency: '42',
|
|
148
|
-
principalId:
|
|
149
|
-
...
|
|
160
|
+
principalId: result.principalId,
|
|
161
|
+
...result.context
|
|
150
162
|
}; // Set the credentials for the rest of the pipeline
|
|
151
|
-
// return resolve(
|
|
152
163
|
|
|
153
164
|
return h.authenticated({
|
|
154
165
|
credentials: {
|
|
155
166
|
authorizer,
|
|
156
|
-
context:
|
|
157
|
-
principalId:
|
|
158
|
-
usageIdentifierKey:
|
|
167
|
+
context: result.context,
|
|
168
|
+
principalId: result.principalId,
|
|
169
|
+
usageIdentifierKey: result.usageIdentifierKey
|
|
159
170
|
}
|
|
160
171
|
});
|
|
161
172
|
} catch (err) {
|
|
@@ -13,6 +13,10 @@ var _serverlessLog = _interopRequireDefault(require("../../serverlessLog.js"));
|
|
|
13
13
|
|
|
14
14
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
15
|
|
|
16
|
+
const {
|
|
17
|
+
isArray
|
|
18
|
+
} = Array;
|
|
19
|
+
|
|
16
20
|
function createAuthScheme(jwtOptions, {
|
|
17
21
|
log
|
|
18
22
|
}) {
|
|
@@ -82,8 +86,8 @@ function createAuthScheme(jwtOptions, {
|
|
|
82
86
|
return _boom.default.unauthorized('JWT Token not from correct issuer url');
|
|
83
87
|
}
|
|
84
88
|
|
|
85
|
-
const validAudiences =
|
|
86
|
-
const providedAudiences =
|
|
89
|
+
const validAudiences = isArray(jwtOptions.audience) ? jwtOptions.audience : [jwtOptions.audience];
|
|
90
|
+
const providedAudiences = isArray(aud) ? aud : [aud];
|
|
87
91
|
const validAudienceProvided = providedAudiences.some(a => validAudiences.includes(a));
|
|
88
92
|
|
|
89
93
|
if (!validAudienceProvided && !validAudiences.includes(clientId)) {
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
+
var _process = require("process");
|
|
9
|
+
|
|
8
10
|
var _renderVelocityTemplateObject = _interopRequireDefault(require("./renderVelocityTemplateObject.js"));
|
|
9
11
|
|
|
10
12
|
var _VelocityContext = _interopRequireDefault(require("./VelocityContext.js"));
|
|
@@ -17,6 +19,10 @@ var id = 0;
|
|
|
17
19
|
|
|
18
20
|
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
19
21
|
|
|
22
|
+
const {
|
|
23
|
+
parse
|
|
24
|
+
} = JSON;
|
|
25
|
+
|
|
20
26
|
var _path = /*#__PURE__*/_classPrivateFieldLooseKey("path");
|
|
21
27
|
|
|
22
28
|
var _request = /*#__PURE__*/_classPrivateFieldLooseKey("request");
|
|
@@ -51,6 +57,26 @@ class LambdaIntegrationEvent {
|
|
|
51
57
|
}
|
|
52
58
|
|
|
53
59
|
create() {
|
|
60
|
+
if (_process.env.AUTHORIZER) {
|
|
61
|
+
try {
|
|
62
|
+
const authorizerContext = parse(_process.env.AUTHORIZER);
|
|
63
|
+
|
|
64
|
+
if (authorizerContext) {
|
|
65
|
+
_classPrivateFieldLooseBase(this, _request)[_request].auth = { ..._classPrivateFieldLooseBase(this, _request)[_request].auth,
|
|
66
|
+
credentials: {
|
|
67
|
+
authorizer: authorizerContext
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
if (this.log) {
|
|
73
|
+
this.log.error('Could not parse process.env.AUTHORIZER, make sure it is correct JSON');
|
|
74
|
+
} else {
|
|
75
|
+
console.error('Serverless-offline: Could not parse process.env.AUTHORIZER, make sure it is correct JSON.');
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
54
80
|
const velocityContext = new _VelocityContext.default(_classPrivateFieldLooseBase(this, _request)[_request], _classPrivateFieldLooseBase(this, _stage)[_stage], _classPrivateFieldLooseBase(this, _request)[_request].payload || {}, _classPrivateFieldLooseBase(this, _path)[_path]).getContext();
|
|
55
81
|
const event = (0, _renderVelocityTemplateObject.default)(_classPrivateFieldLooseBase(this, _requestTemplate)[_requestTemplate], velocityContext, this.v3Utils);
|
|
56
82
|
return event;
|
|
@@ -7,6 +7,8 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _buffer = require("buffer");
|
|
9
9
|
|
|
10
|
+
var _process = require("process");
|
|
11
|
+
|
|
10
12
|
var _jsonwebtoken = require("jsonwebtoken");
|
|
11
13
|
|
|
12
14
|
var _index = require("../../../utils/index.js");
|
|
@@ -42,7 +44,7 @@ var _stageVariables = /*#__PURE__*/_classPrivateFieldLooseKey("stageVariables");
|
|
|
42
44
|
var _additionalRequestContext = /*#__PURE__*/_classPrivateFieldLooseKey("additionalRequestContext");
|
|
43
45
|
|
|
44
46
|
class LambdaProxyIntegrationEvent {
|
|
45
|
-
constructor(request, stage, path, stageVariables, routeKey
|
|
47
|
+
constructor(request, stage, path, stageVariables, routeKey, additionalRequestContext, v3Utils) {
|
|
46
48
|
Object.defineProperty(this, _path, {
|
|
47
49
|
writable: true,
|
|
48
50
|
value: null
|
|
@@ -88,14 +90,14 @@ class LambdaProxyIntegrationEvent {
|
|
|
88
90
|
const authContext = _classPrivateFieldLooseBase(this, _request)[_request].auth && _classPrivateFieldLooseBase(this, _request)[_request].auth.credentials && _classPrivateFieldLooseBase(this, _request)[_request].auth.credentials.context || {};
|
|
89
91
|
let authAuthorizer;
|
|
90
92
|
|
|
91
|
-
if (
|
|
93
|
+
if (_process.env.AUTHORIZER) {
|
|
92
94
|
try {
|
|
93
|
-
authAuthorizer = parse(
|
|
95
|
+
authAuthorizer = parse(_process.env.AUTHORIZER);
|
|
94
96
|
} catch (error) {
|
|
95
97
|
if (this.log) {
|
|
96
|
-
this.log.error('Could not parse
|
|
98
|
+
this.log.error('Could not parse env.AUTHORIZER, make sure it is correct JSON');
|
|
97
99
|
} else {
|
|
98
|
-
console.error('Serverless-offline: Could not parse
|
|
100
|
+
console.error('Serverless-offline: Could not parse env.AUTHORIZER, make sure it is correct JSON.');
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -201,7 +203,7 @@ class LambdaProxyIntegrationEvent {
|
|
|
201
203
|
claims,
|
|
202
204
|
scopes,
|
|
203
205
|
// 'principalId' should have higher priority
|
|
204
|
-
principalId: authPrincipalId ||
|
|
206
|
+
principalId: authPrincipalId || _process.env.PRINCIPAL_ID || 'offlineContext_authorizer_principalId' // See #24
|
|
205
207
|
|
|
206
208
|
}),
|
|
207
209
|
domainName: 'offlineContext_domainName',
|
|
@@ -210,14 +212,14 @@ class LambdaProxyIntegrationEvent {
|
|
|
210
212
|
httpMethod,
|
|
211
213
|
identity: {
|
|
212
214
|
accessKey: null,
|
|
213
|
-
accountId:
|
|
214
|
-
apiKey:
|
|
215
|
-
apiKeyId:
|
|
216
|
-
caller:
|
|
217
|
-
cognitoAuthenticationProvider: _headers['cognito-authentication-provider'] ||
|
|
218
|
-
cognitoAuthenticationType:
|
|
219
|
-
cognitoIdentityId: _headers['cognito-identity-id'] ||
|
|
220
|
-
cognitoIdentityPoolId:
|
|
215
|
+
accountId: _process.env.SLS_ACCOUNT_ID || 'offlineContext_accountId',
|
|
216
|
+
apiKey: _process.env.SLS_API_KEY || 'offlineContext_apiKey',
|
|
217
|
+
apiKeyId: _process.env.SLS_API_KEY_ID || 'offlineContext_apiKeyId',
|
|
218
|
+
caller: _process.env.SLS_CALLER || 'offlineContext_caller',
|
|
219
|
+
cognitoAuthenticationProvider: _headers['cognito-authentication-provider'] || _process.env.SLS_COGNITO_AUTHENTICATION_PROVIDER || 'offlineContext_cognitoAuthenticationProvider',
|
|
220
|
+
cognitoAuthenticationType: _process.env.SLS_COGNITO_AUTHENTICATION_TYPE || 'offlineContext_cognitoAuthenticationType',
|
|
221
|
+
cognitoIdentityId: _headers['cognito-identity-id'] || _process.env.SLS_COGNITO_IDENTITY_ID || 'offlineContext_cognitoIdentityId',
|
|
222
|
+
cognitoIdentityPoolId: _process.env.SLS_COGNITO_IDENTITY_POOL_ID || 'offlineContext_cognitoIdentityPoolId',
|
|
221
223
|
principalOrgId: null,
|
|
222
224
|
sourceIp: remoteAddress,
|
|
223
225
|
user: 'offlineContext_user',
|
|
@@ -7,6 +7,8 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _buffer = require("buffer");
|
|
9
9
|
|
|
10
|
+
var _process = require("process");
|
|
11
|
+
|
|
10
12
|
var _jsonwebtoken = require("jsonwebtoken");
|
|
11
13
|
|
|
12
14
|
var _index = require("../../../utils/index.js");
|
|
@@ -18,13 +20,15 @@ var id = 0;
|
|
|
18
20
|
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
19
21
|
|
|
20
22
|
const {
|
|
21
|
-
|
|
22
|
-
} =
|
|
23
|
+
isArray
|
|
24
|
+
} = Array;
|
|
23
25
|
const {
|
|
24
26
|
parse
|
|
25
27
|
} = JSON;
|
|
26
28
|
const {
|
|
27
|
-
assign
|
|
29
|
+
assign,
|
|
30
|
+
entries,
|
|
31
|
+
fromEntries
|
|
28
32
|
} = Object; // https://www.serverless.com/framework/docs/providers/aws/events/http-api/
|
|
29
33
|
// https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html
|
|
30
34
|
|
|
@@ -78,9 +82,9 @@ class LambdaProxyIntegrationEventV2 {
|
|
|
78
82
|
const authContext = _classPrivateFieldLooseBase(this, _request)[_request].auth && _classPrivateFieldLooseBase(this, _request)[_request].auth.credentials && _classPrivateFieldLooseBase(this, _request)[_request].auth.credentials.context || {};
|
|
79
83
|
let authAuthorizer;
|
|
80
84
|
|
|
81
|
-
if (
|
|
85
|
+
if (_process.env.AUTHORIZER) {
|
|
82
86
|
try {
|
|
83
|
-
authAuthorizer = parse(
|
|
87
|
+
authAuthorizer = parse(_process.env.AUTHORIZER);
|
|
84
88
|
} catch (error) {
|
|
85
89
|
if (this.log) {
|
|
86
90
|
this.log.error('Could not parse process.env.AUTHORIZER, make sure it is correct JSON');
|
|
@@ -97,7 +101,7 @@ class LambdaProxyIntegrationEventV2 {
|
|
|
97
101
|
} = _classPrivateFieldLooseBase(this, _request)[_request].raw.req; // NOTE FIXME request.raw.req.rawHeaders can only be null for testing (hapi shot inject())
|
|
98
102
|
|
|
99
103
|
|
|
100
|
-
const headers = (0, _index.parseHeaders)(rawHeaders || []) || {};
|
|
104
|
+
const headers = (0, _index.lowerCaseKeys)((0, _index.parseHeaders)(rawHeaders || [])) || {};
|
|
101
105
|
|
|
102
106
|
if (headers['sls-offline-authorizer-override']) {
|
|
103
107
|
try {
|
|
@@ -117,13 +121,13 @@ class LambdaProxyIntegrationEventV2 {
|
|
|
117
121
|
body = _classPrivateFieldLooseBase(this, _request)[_request].rawPayload;
|
|
118
122
|
}
|
|
119
123
|
|
|
120
|
-
if (!headers['
|
|
121
|
-
headers['
|
|
124
|
+
if (!headers['content-length'] && (typeof body === 'string' || body instanceof _buffer.Buffer || body instanceof ArrayBuffer)) {
|
|
125
|
+
headers['content-length'] = String(_buffer.Buffer.byteLength(body));
|
|
122
126
|
} // Set a default Content-Type if not provided.
|
|
123
127
|
|
|
124
128
|
|
|
125
|
-
if (!headers['
|
|
126
|
-
headers['
|
|
129
|
+
if (!headers['content-type']) {
|
|
130
|
+
headers['content-type'] = 'application/json';
|
|
127
131
|
}
|
|
128
132
|
} else if (typeof body === 'undefined' || body === '') {
|
|
129
133
|
body = null;
|
|
@@ -169,7 +173,13 @@ class LambdaProxyIntegrationEventV2 {
|
|
|
169
173
|
const httpMethod = method.toUpperCase();
|
|
170
174
|
const requestTime = (0, _index.formatToClfTime)(received);
|
|
171
175
|
const requestTimeEpoch = received;
|
|
172
|
-
const cookies =
|
|
176
|
+
const cookies = entries(_classPrivateFieldLooseBase(this, _request)[_request].state).flatMap(([key, value]) => {
|
|
177
|
+
if (isArray(value)) {
|
|
178
|
+
return value.map(v => `${key}=${v}`);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return `${key}=${value}`;
|
|
182
|
+
});
|
|
173
183
|
return {
|
|
174
184
|
version: '2.0',
|
|
175
185
|
routeKey: _classPrivateFieldLooseBase(this, _routeKey)[_routeKey],
|
|
@@ -177,7 +187,7 @@ class LambdaProxyIntegrationEventV2 {
|
|
|
177
187
|
rawQueryString: _classPrivateFieldLooseBase(this, _request)[_request].url.searchParams.toString(),
|
|
178
188
|
cookies,
|
|
179
189
|
headers,
|
|
180
|
-
queryStringParameters: _classPrivateFieldLooseBase(this, _request)[_request].url.search ?
|
|
190
|
+
queryStringParameters: _classPrivateFieldLooseBase(this, _request)[_request].url.search ? fromEntries(Array.from(_classPrivateFieldLooseBase(this, _request)[_request].url.searchParams)) : null,
|
|
181
191
|
requestContext: {
|
|
182
192
|
accountId: 'offlineContext_accountId',
|
|
183
193
|
apiId: 'offlineContext_apiId',
|
|
@@ -7,6 +7,8 @@ exports.default = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _buffer = require("buffer");
|
|
9
9
|
|
|
10
|
+
var _process = require("process");
|
|
11
|
+
|
|
10
12
|
var _jsStringEscape = _interopRequireDefault(require("js-string-escape"));
|
|
11
13
|
|
|
12
14
|
var _jsonwebtoken = require("jsonwebtoken");
|
|
@@ -102,7 +104,7 @@ class VelocityContext {
|
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
if (!authorizer) authorizer = {};
|
|
105
|
-
authorizer.principalId = authPrincipalId ||
|
|
107
|
+
authorizer.principalId = authPrincipalId || _process.env.PRINCIPAL_ID || 'offlineContext_authorizer_principalId'; // See #24
|
|
106
108
|
|
|
107
109
|
if (token) {
|
|
108
110
|
try {
|
|
@@ -15,6 +15,9 @@ var _index = require("../../../utils/index.js");
|
|
|
15
15
|
|
|
16
16
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
17
|
|
|
18
|
+
const {
|
|
19
|
+
parse
|
|
20
|
+
} = JSON;
|
|
18
21
|
const {
|
|
19
22
|
entries
|
|
20
23
|
} = Object;
|
|
@@ -23,7 +26,7 @@ function tryToParseJSON(string) {
|
|
|
23
26
|
let parsed;
|
|
24
27
|
|
|
25
28
|
try {
|
|
26
|
-
parsed =
|
|
29
|
+
parsed = parse(string);
|
|
27
30
|
} catch (err) {// nothing! Some things are not meant to be parsed.
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -19,7 +19,7 @@ var id = 0;
|
|
|
19
19
|
|
|
20
20
|
function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + name; }
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
const CRON_LENGTH_WITH_YEAR = 6;
|
|
23
23
|
const {
|
|
24
24
|
stringify
|
|
25
25
|
} = JSON;
|
|
@@ -106,14 +106,15 @@ class Schedule {
|
|
|
106
106
|
}
|
|
107
107
|
});
|
|
108
108
|
});
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
// }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_convertCronSyntax(cronString) {
|
|
112
|
+
if (cronString.split(' ').length < CRON_LENGTH_WITH_YEAR) {
|
|
113
|
+
return cronString;
|
|
114
|
+
}
|
|
116
115
|
|
|
116
|
+
return cronString.replace(/\s\S+$/, '');
|
|
117
|
+
}
|
|
117
118
|
|
|
118
119
|
_convertRateToCron(rate) {
|
|
119
120
|
const [number, unit] = rate.split(' ');
|
|
@@ -146,7 +147,7 @@ class Schedule {
|
|
|
146
147
|
const params = scheduleEvent.replace('rate(', '').replace('cron(', '').replace(')', '');
|
|
147
148
|
|
|
148
149
|
if (scheduleEvent.startsWith('cron(')) {
|
|
149
|
-
|
|
150
|
+
return this._convertCronSyntax(params);
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
if (scheduleEvent.startsWith('rate(')) {
|
|
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
|
|
8
|
+
var _process = require("process");
|
|
9
|
+
|
|
8
10
|
var _hapi = require("@hapi/hapi");
|
|
9
11
|
|
|
10
12
|
var _index = require("./http-routes/index.js");
|
|
@@ -86,7 +88,7 @@ class HttpServer {
|
|
|
86
88
|
console.error(`Unexpected error while starting serverless-offline websocket server on port ${websocketPort}:`, err);
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
|
|
91
|
+
(0, _process.exit)(1);
|
|
90
92
|
}
|
|
91
93
|
|
|
92
94
|
if (this.log) {
|