@comicrelief/lambda-wrapper 1.10.1 → 2.0.0-beta.2
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 +172 -47
- package/dist/core/DependencyAwareClass.d.ts +15 -0
- package/dist/core/DependencyAwareClass.d.ts.map +1 -0
- package/dist/core/DependencyAwareClass.js +20 -0
- package/dist/core/DependencyAwareClass.js.map +1 -0
- package/dist/core/DependencyInjection.d.ts +62 -0
- package/dist/core/DependencyInjection.d.ts.map +1 -0
- package/dist/core/DependencyInjection.js +83 -0
- package/dist/core/DependencyInjection.js.map +1 -0
- package/dist/core/LambdaWrapper.d.ts +61 -0
- package/dist/core/LambdaWrapper.d.ts.map +1 -0
- package/dist/core/LambdaWrapper.js +126 -0
- package/dist/core/LambdaWrapper.js.map +1 -0
- package/dist/core/config.d.ts +20 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +21 -0
- package/dist/core/config.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -162
- package/dist/index.js.map +1 -0
- package/dist/models/ResponseModel.d.ts +91 -0
- package/dist/models/ResponseModel.d.ts.map +1 -0
- package/dist/models/ResponseModel.js +100 -0
- package/dist/models/ResponseModel.js.map +1 -0
- package/dist/models/SQSMessageModel.d.ts +46 -0
- package/dist/models/SQSMessageModel.d.ts.map +1 -0
- package/dist/models/SQSMessageModel.js +65 -0
- package/dist/models/SQSMessageModel.js.map +1 -0
- package/dist/models/StatusModel.d.ts +40 -0
- package/dist/models/StatusModel.d.ts.map +1 -0
- package/dist/models/StatusModel.js +50 -0
- package/dist/models/StatusModel.js.map +1 -0
- package/dist/services/BaseConfigService.d.ts +101 -0
- package/dist/services/BaseConfigService.d.ts.map +1 -0
- package/dist/services/BaseConfigService.js +180 -0
- package/dist/services/BaseConfigService.js.map +1 -0
- package/dist/services/HTTPService.d.ts +29 -0
- package/dist/services/HTTPService.d.ts.map +1 -0
- package/dist/services/HTTPService.js +55 -0
- package/dist/services/HTTPService.js.map +1 -0
- package/dist/services/LoggerService.d.ts +102 -0
- package/dist/services/LoggerService.d.ts.map +1 -0
- package/dist/services/LoggerService.js +258 -0
- package/dist/services/LoggerService.js.map +1 -0
- package/dist/services/RequestService.d.ts +119 -0
- package/dist/services/RequestService.d.ts.map +1 -0
- package/dist/services/RequestService.js +293 -0
- package/dist/services/RequestService.js.map +1 -0
- package/dist/services/SQSService.d.ts +181 -0
- package/dist/services/SQSService.d.ts.map +1 -0
- package/dist/services/SQSService.js +366 -0
- package/dist/services/SQSService.js.map +1 -0
- package/dist/services/TimerService.d.ts +22 -0
- package/dist/services/TimerService.d.ts.map +1 -0
- package/dist/services/TimerService.js +40 -0
- package/dist/services/TimerService.js.map +1 -0
- package/dist/utils/LambdaTermination.d.ts +14 -0
- package/dist/utils/LambdaTermination.d.ts.map +1 -0
- package/dist/utils/LambdaTermination.js +23 -0
- package/dist/utils/LambdaTermination.js.map +1 -0
- package/dist/utils/PromisifiedDelay.d.ts +17 -0
- package/dist/utils/PromisifiedDelay.d.ts.map +1 -0
- package/dist/utils/PromisifiedDelay.js +48 -0
- package/dist/utils/PromisifiedDelay.js.map +1 -0
- package/package.json +29 -19
- package/.eslintrc.yml +0 -16
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/main.yml +0 -74
- package/babel.config.js +0 -13
- package/dist/Config/Dependencies.js +0 -40
- package/dist/DependencyInjection/DependencyAware.class.js +0 -47
- package/dist/DependencyInjection/DependencyInjection.class.js +0 -131
- package/dist/Model/CloudEvent.model.js +0 -156
- package/dist/Model/Model.model.js +0 -45
- package/dist/Model/Response.model.js +0 -150
- package/dist/Model/SQS/MarketingPreference.constraints.json +0 -28
- package/dist/Model/SQS/MarketingPreference.model.js +0 -641
- package/dist/Model/SQS/Message.model.js +0 -104
- package/dist/Model/Status.model.js +0 -82
- package/dist/Service/BaseConfig.service.js +0 -225
- package/dist/Service/HTTP.service.js +0 -70
- package/dist/Service/Logger.service.js +0 -293
- package/dist/Service/Request.service.js +0 -341
- package/dist/Service/SQS.service.js +0 -420
- package/dist/Service/Timer.service.js +0 -55
- package/dist/Wrapper/LambdaTermination.js +0 -39
- package/dist/Wrapper/LambdaWrapper.js +0 -164
- package/dist/Wrapper/PromisifiedDelay.js +0 -59
|
@@ -1,293 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = void 0;
|
|
7
|
-
|
|
8
|
-
var Sentry = _interopRequireWildcard(require("@sentry/node"));
|
|
9
|
-
|
|
10
|
-
var _epsagon = _interopRequireDefault(require("epsagon"));
|
|
11
|
-
|
|
12
|
-
var _winston = _interopRequireDefault(require("winston"));
|
|
13
|
-
|
|
14
|
-
var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
|
|
15
|
-
|
|
16
|
-
var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
|
|
17
|
-
|
|
18
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
-
|
|
20
|
-
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); }
|
|
21
|
-
|
|
22
|
-
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; }
|
|
23
|
-
|
|
24
|
-
// Instantiate the sentry client
|
|
25
|
-
const sentryIsAvailable = typeof process.env.RAVEN_DSN !== 'undefined' && typeof process.env.RAVEN_DSN === 'string' && process.env.RAVEN_DSN !== 'undefined';
|
|
26
|
-
|
|
27
|
-
if (sentryIsAvailable) {
|
|
28
|
-
Sentry.init({
|
|
29
|
-
dsn: process.env.RAVEN_DSN,
|
|
30
|
-
shutdownTimeout: 5,
|
|
31
|
-
environment: process.env.STAGE
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* LoggerService class
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class LoggerService extends _DependencyAware.default {
|
|
40
|
-
constructor(di) {
|
|
41
|
-
super(di);
|
|
42
|
-
this.sentry = null;
|
|
43
|
-
this.winston = null;
|
|
44
|
-
const container = this.getContainer();
|
|
45
|
-
const event = container.getEvent();
|
|
46
|
-
const context = container.getContext(); // Set sentry client context
|
|
47
|
-
|
|
48
|
-
if (sentryIsAvailable && !container.isOffline) {
|
|
49
|
-
Sentry.configureScope(scope => {
|
|
50
|
-
scope.setTags({
|
|
51
|
-
Event: event,
|
|
52
|
-
Context: context
|
|
53
|
-
});
|
|
54
|
-
scope.setExtras({
|
|
55
|
-
lambda: context.functionName,
|
|
56
|
-
memory_size: context.memoryLimitInMB,
|
|
57
|
-
log_group: context.log_group_name,
|
|
58
|
-
log_stream: context.log_stream_name,
|
|
59
|
-
stage: process.env.STAGE,
|
|
60
|
-
path: event.path,
|
|
61
|
-
httpMethod: event.httpMethod
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
this.sentry = Sentry;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* Returns a Winston logger object
|
|
69
|
-
* configured for our lambdas.
|
|
70
|
-
*
|
|
71
|
-
* Note:
|
|
72
|
-
*
|
|
73
|
-
* If the lambda is executed
|
|
74
|
-
* in a `serverless-offline` context
|
|
75
|
-
* the log output to console will be pretty printed.
|
|
76
|
-
*/
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
getLogger() {
|
|
80
|
-
const loggerFormats = [_winston.default.format.json({
|
|
81
|
-
replacer: (key, value) => {
|
|
82
|
-
if (value instanceof Buffer) {
|
|
83
|
-
return value.toString('base64');
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (value instanceof Error) {
|
|
87
|
-
const error = {};
|
|
88
|
-
Object.getOwnPropertyNames(value).forEach(objectKey => {
|
|
89
|
-
error[objectKey] = value[objectKey];
|
|
90
|
-
});
|
|
91
|
-
return error;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return value;
|
|
95
|
-
}
|
|
96
|
-
})];
|
|
97
|
-
|
|
98
|
-
if (this.getContainer().isOffline) {
|
|
99
|
-
loggerFormats.push(_winston.default.format.prettyPrint());
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return _winston.default.createLogger({
|
|
103
|
-
level: 'info',
|
|
104
|
-
format: _winston.default.format.combine(...loggerFormats),
|
|
105
|
-
transports: [new _winston.default.transports.Console()]
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
/**
|
|
109
|
-
* Returns the logger.
|
|
110
|
-
*
|
|
111
|
-
* Uses a cached `Winston` object
|
|
112
|
-
* if it has been already generated,
|
|
113
|
-
* otherwise it generates one.
|
|
114
|
-
*/
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
get logger() {
|
|
118
|
-
if (!this.winston) {
|
|
119
|
-
this.winston = this.getLogger();
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
return this.winston;
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* While handling an error, lambda wrapper should
|
|
126
|
-
* recognise axios errors and trim down the information.
|
|
127
|
-
*
|
|
128
|
-
* Keep the following keys:
|
|
129
|
-
* - message.config
|
|
130
|
-
* - message.message
|
|
131
|
-
* - message.response?.status
|
|
132
|
-
* - message.response?.data
|
|
133
|
-
*
|
|
134
|
-
* @param {object} error
|
|
135
|
-
*/
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
static processAxiosError(error) {
|
|
139
|
-
const processed = {
|
|
140
|
-
config: error.config,
|
|
141
|
-
message: error.message
|
|
142
|
-
}; // It's pretty common for axios errors
|
|
143
|
-
// to not have.response e.g.when there's
|
|
144
|
-
// a network error or timeout.
|
|
145
|
-
// These errors will have .request but not .response.
|
|
146
|
-
|
|
147
|
-
if (error.response) {
|
|
148
|
-
processed.response = {
|
|
149
|
-
status: error.response.status,
|
|
150
|
-
data: error.response.data
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return processed;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Transform the original message
|
|
158
|
-
* before it is passed to the winston logger
|
|
159
|
-
*
|
|
160
|
-
* @param {string|object} message
|
|
161
|
-
*/
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
processMessage(message = '') {
|
|
165
|
-
let processed = message;
|
|
166
|
-
|
|
167
|
-
if (processed && processed.isAxiosError) {
|
|
168
|
-
processed = this.constructor.processAxiosError(processed);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return processed;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Log Error Message
|
|
175
|
-
*
|
|
176
|
-
* @param error object
|
|
177
|
-
* @param message string
|
|
178
|
-
*/
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
error(error, message = '') {
|
|
182
|
-
if (sentryIsAvailable && error instanceof Error) {
|
|
183
|
-
Sentry.captureException(error);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined' && error instanceof Error) {
|
|
187
|
-
_epsagon.default.setError(error);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
this.logger.log('error', message, {
|
|
191
|
-
error: this.processMessage(error)
|
|
192
|
-
});
|
|
193
|
-
this.label('error', true);
|
|
194
|
-
this.metric('error', 'error', true);
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* Get sentry client
|
|
198
|
-
*
|
|
199
|
-
* @returns {null|*}
|
|
200
|
-
*/
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
getSentry() {
|
|
204
|
-
return this.sentry;
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Log Information Message
|
|
208
|
-
*
|
|
209
|
-
* @param message string
|
|
210
|
-
*/
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
info(message) {
|
|
214
|
-
this.logger.log('info', this.processMessage(message));
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Logs an error, using `LoggerService.error`
|
|
218
|
-
* or `LoggerService.info` based on
|
|
219
|
-
* `process.env.LOGGER_SOFT_WARNING`.
|
|
220
|
-
*
|
|
221
|
-
* Please note that `LoggerService.error` and `LoggerService.info`
|
|
222
|
-
* have different signatures. The function uses the shared argument
|
|
223
|
-
* instead of introducing ambiguity.
|
|
224
|
-
*
|
|
225
|
-
* @param error
|
|
226
|
-
*/
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
warning(error) {
|
|
230
|
-
const softWarningValues = ['true', '1'];
|
|
231
|
-
|
|
232
|
-
if (softWarningValues.includes(process.env.LOGGER_SOFT_WARNING)) {
|
|
233
|
-
return this.info(error);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
return this.error(error);
|
|
237
|
-
}
|
|
238
|
-
/**
|
|
239
|
-
* Add a label
|
|
240
|
-
*
|
|
241
|
-
* @param descriptor string
|
|
242
|
-
* @param silent boolean
|
|
243
|
-
*/
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
label(descriptor, silent = false) {
|
|
247
|
-
if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined') {
|
|
248
|
-
_epsagon.default.label(descriptor, true);
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (silent === false) {
|
|
252
|
-
this.logger.log('info', `label - ${descriptor}`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Add a metric
|
|
257
|
-
*
|
|
258
|
-
* @param descriptor string
|
|
259
|
-
* @param stat integer | string
|
|
260
|
-
* @param silent boolean
|
|
261
|
-
*/
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
metric(descriptor, stat, silent = false) {
|
|
265
|
-
if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined') {
|
|
266
|
-
_epsagon.default.label(descriptor, stat);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
if (silent === false) {
|
|
270
|
-
this.logger.log('info', `metric - ${descriptor} - ${stat}`);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Logs an object so that it can be inspected
|
|
275
|
-
*
|
|
276
|
-
* @param action - What are we doing with the object, i.e. 'Processing'
|
|
277
|
-
* @param object - The object to be stored in logs
|
|
278
|
-
* @param level - 'error', 'warning' or 'info'
|
|
279
|
-
*/
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
object(action, object, level = 'info') {
|
|
283
|
-
if (!['error', 'warning', 'info'].includes(level)) {
|
|
284
|
-
throw new Error('Unrecognised log level');
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
const payload = JSON.stringify(object, null, 4);
|
|
288
|
-
return this[level](`${action}: '${payload}'`);
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
exports.default = LoggerService;
|
|
@@ -1,341 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = exports.REQUEST_TYPES = exports.HTTP_METHODS_WITH_PAYLOADS = exports.HTTP_METHODS_WITHOUT_PAYLOADS = exports.ERROR_TYPES = void 0;
|
|
7
|
-
|
|
8
|
-
var _querystring = _interopRequireDefault(require("querystring"));
|
|
9
|
-
|
|
10
|
-
var _useragent = _interopRequireDefault(require("useragent"));
|
|
11
|
-
|
|
12
|
-
var _validate = _interopRequireDefault(require("validate.js/validate"));
|
|
13
|
-
|
|
14
|
-
var _xml2js = _interopRequireDefault(require("xml2js"));
|
|
15
|
-
|
|
16
|
-
var _Dependencies = require("../Config/Dependencies");
|
|
17
|
-
|
|
18
|
-
var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
|
|
19
|
-
|
|
20
|
-
var _Response = _interopRequireDefault(require("../Model/Response.model"));
|
|
21
|
-
|
|
22
|
-
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
23
|
-
|
|
24
|
-
/* eslint-disable class-methods-use-this */
|
|
25
|
-
|
|
26
|
-
/* eslint-disable sonarjs/no-duplicate-string */
|
|
27
|
-
const REQUEST_TYPES = {
|
|
28
|
-
DELETE: 'DELETE',
|
|
29
|
-
GET: 'GET',
|
|
30
|
-
HEAD: 'HEAD',
|
|
31
|
-
OPTIONS: 'OPTIONS',
|
|
32
|
-
PATCH: 'PATCH',
|
|
33
|
-
POST: 'POST',
|
|
34
|
-
PUT: 'PUT'
|
|
35
|
-
};
|
|
36
|
-
exports.REQUEST_TYPES = REQUEST_TYPES;
|
|
37
|
-
const HTTP_METHODS_WITHOUT_PAYLOADS = [REQUEST_TYPES.DELETE, REQUEST_TYPES.GET, REQUEST_TYPES.HEAD, REQUEST_TYPES.OPTIONS];
|
|
38
|
-
exports.HTTP_METHODS_WITHOUT_PAYLOADS = HTTP_METHODS_WITHOUT_PAYLOADS;
|
|
39
|
-
const HTTP_METHODS_WITH_PAYLOADS = [REQUEST_TYPES.PATCH, REQUEST_TYPES.POST, REQUEST_TYPES.PUT]; // Define action specific error types
|
|
40
|
-
|
|
41
|
-
exports.HTTP_METHODS_WITH_PAYLOADS = HTTP_METHODS_WITH_PAYLOADS;
|
|
42
|
-
const ERROR_TYPES = {
|
|
43
|
-
VALIDATION_ERROR: new _Response.default({}, 400, 'required fields are missing')
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* RequestService class
|
|
47
|
-
*/
|
|
48
|
-
|
|
49
|
-
exports.ERROR_TYPES = ERROR_TYPES;
|
|
50
|
-
|
|
51
|
-
class RequestService extends _DependencyAware.default {
|
|
52
|
-
/**
|
|
53
|
-
* Get a parameter from the request.
|
|
54
|
-
*
|
|
55
|
-
* @param parameter
|
|
56
|
-
* @param ifNull
|
|
57
|
-
* @param requestType
|
|
58
|
-
*/
|
|
59
|
-
get(parameter, ifNull = null, requestType = null) {
|
|
60
|
-
const queryParameters = this.getAll(requestType);
|
|
61
|
-
|
|
62
|
-
if (queryParameters === null) {
|
|
63
|
-
return ifNull;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return typeof queryParameters[parameter] !== 'undefined' ? queryParameters[parameter] : ifNull;
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Get all HTTP headers included in the request.
|
|
70
|
-
*
|
|
71
|
-
* @returns {object} An object with a key for each header.
|
|
72
|
-
*/
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
getAllHeaders() {
|
|
76
|
-
return { ...this.getContainer().getEvent().headers
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Get an HTTP header from the request.
|
|
81
|
-
*
|
|
82
|
-
* The header name is case-insensitive.
|
|
83
|
-
*
|
|
84
|
-
* @param {string} name The name of the header.
|
|
85
|
-
* @param {string} [whenMissing] Value to return if the header is missing.
|
|
86
|
-
* (default: empty string)
|
|
87
|
-
* @returns {string}
|
|
88
|
-
*/
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
getHeader(name, whenMissing = '') {
|
|
92
|
-
const headers = this.getAllHeaders();
|
|
93
|
-
|
|
94
|
-
if (!headers) {
|
|
95
|
-
return whenMissing;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const lowerName = name.toLowerCase();
|
|
99
|
-
const key = Object.keys(headers).find(k => k.toLowerCase() === lowerName);
|
|
100
|
-
return key && headers[key] || whenMissing;
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* Get authorization token
|
|
104
|
-
*
|
|
105
|
-
* @returns {*}
|
|
106
|
-
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
getAuthorizationToken() {
|
|
110
|
-
const authorization = this.getHeader('Authorization');
|
|
111
|
-
|
|
112
|
-
if (!authorization) {
|
|
113
|
-
return null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const tokenParts = authorization.split(' ');
|
|
117
|
-
const tokenValue = tokenParts[1];
|
|
118
|
-
|
|
119
|
-
if (!(tokenParts[0].toLowerCase() === 'bearer' && tokenValue)) {
|
|
120
|
-
return null;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
return tokenValue;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Get a path parameter
|
|
127
|
-
*
|
|
128
|
-
* @param parameter
|
|
129
|
-
* @param ifNull mixed
|
|
130
|
-
*/
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
getPathParameter(parameter = null, ifNull = {}) {
|
|
134
|
-
const event = this.getContainer().getEvent(); // If no parameter has been requested, return all path parameters
|
|
135
|
-
|
|
136
|
-
if (parameter === null && typeof event.pathParameters === 'object') {
|
|
137
|
-
return event.pathParameters;
|
|
138
|
-
} // If a specifc parameter has been requested, return the parameter if it exists
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (typeof parameter === 'string' && typeof event.pathParameters === 'object' && event.pathParameters !== null && typeof event.pathParameters[parameter] !== 'undefined') {
|
|
142
|
-
return event.pathParameters[parameter];
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return ifNull;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Get all request parameters
|
|
149
|
-
*
|
|
150
|
-
* @param requestType
|
|
151
|
-
* @returns {{}}
|
|
152
|
-
*/
|
|
153
|
-
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
getAll(requestType = null) {
|
|
157
|
-
const event = this.getContainer().getEvent();
|
|
158
|
-
|
|
159
|
-
if (HTTP_METHODS_WITHOUT_PAYLOADS.includes(event.httpMethod) || HTTP_METHODS_WITHOUT_PAYLOADS.includes(requestType)) {
|
|
160
|
-
// get simple parameters
|
|
161
|
-
const params = { ...event.queryStringParameters
|
|
162
|
-
}; // add array parameters as arrays
|
|
163
|
-
|
|
164
|
-
Object.keys(params).filter(key => key.endsWith('[]')).forEach(key => {
|
|
165
|
-
params[key] = event.multiValueQueryStringParameters[key];
|
|
166
|
-
});
|
|
167
|
-
return params;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (HTTP_METHODS_WITH_PAYLOADS.includes(event.httpMethod) || HTTP_METHODS_WITH_PAYLOADS.includes(requestType)) {
|
|
171
|
-
const contentType = this.getHeader('Content-Type');
|
|
172
|
-
let queryParameters = {};
|
|
173
|
-
|
|
174
|
-
if (contentType.includes('application/x-www-form-urlencoded')) {
|
|
175
|
-
queryParameters = _querystring.default.parse(event.body);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if (contentType.includes('application/json')) {
|
|
179
|
-
try {
|
|
180
|
-
queryParameters = JSON.parse(event.body);
|
|
181
|
-
} catch {
|
|
182
|
-
queryParameters = {};
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
if (contentType.includes('text/xml')) {
|
|
187
|
-
_xml2js.default.parseString(event.body, (error, result) => {
|
|
188
|
-
queryParameters = error ? {} : result;
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (contentType.includes('multipart/form-data')) {
|
|
193
|
-
queryParameters = this.parseForm(true);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
return typeof queryParameters !== 'undefined' ? queryParameters : {};
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
return null;
|
|
200
|
-
}
|
|
201
|
-
/**
|
|
202
|
-
* Fetch the request IP address
|
|
203
|
-
*
|
|
204
|
-
* @returns {*}
|
|
205
|
-
*/
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
getIp() {
|
|
209
|
-
const event = this.getContainer().getEvent();
|
|
210
|
-
|
|
211
|
-
if (typeof event.requestContext !== 'undefined' && typeof event.requestContext.identity !== 'undefined' && typeof event.requestContext.identity.sourceIp !== 'undefined') {
|
|
212
|
-
return event.requestContext.identity.sourceIp;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* Get user agent
|
|
219
|
-
*
|
|
220
|
-
* @returns {*}
|
|
221
|
-
*/
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
getUserBrowserAndDevice() {
|
|
225
|
-
const userAgent = this.getHeader('user-agent', null);
|
|
226
|
-
|
|
227
|
-
if (userAgent === null) {
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
const agent = _useragent.default.parse(userAgent);
|
|
233
|
-
|
|
234
|
-
const os = agent.os.toJSON();
|
|
235
|
-
return {
|
|
236
|
-
'browser-type': agent.family,
|
|
237
|
-
'browser-version': agent.toVersion(),
|
|
238
|
-
'device-type': agent.device.family,
|
|
239
|
-
'operating-system': os.family,
|
|
240
|
-
'operating-system-version': agent.os.toVersion()
|
|
241
|
-
};
|
|
242
|
-
} catch {
|
|
243
|
-
this.getContainer().get(_Dependencies.DEFINITIONS.LOGGER).label('user-agent-parsing-failed');
|
|
244
|
-
return null;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
/**
|
|
248
|
-
* Test a request against validation constraints
|
|
249
|
-
*
|
|
250
|
-
* @param constraints
|
|
251
|
-
* @returns {Promise<any>}
|
|
252
|
-
*/
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
validateAgainstConstraints(constraints) {
|
|
256
|
-
const Logger = this.getContainer().get(_Dependencies.DEFINITIONS.LOGGER);
|
|
257
|
-
return new Promise((resolve, reject) => {
|
|
258
|
-
const validation = (0, _validate.default)(this.getAll(), constraints);
|
|
259
|
-
|
|
260
|
-
if (typeof validation === 'undefined') {
|
|
261
|
-
resolve();
|
|
262
|
-
} else {
|
|
263
|
-
Logger.label('request-validation-failed');
|
|
264
|
-
const validationErrorResponse = ERROR_TYPES.VALIDATION_ERROR;
|
|
265
|
-
validationErrorResponse.setBodyVariable('validation_errors', validation);
|
|
266
|
-
reject(validationErrorResponse);
|
|
267
|
-
}
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* Fetch the request multipart form
|
|
272
|
-
*
|
|
273
|
-
* @param useBuffer
|
|
274
|
-
* @returns {*}
|
|
275
|
-
*/
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
parseForm(useBuffer) {
|
|
279
|
-
const event = this.getContainer().getEvent();
|
|
280
|
-
const boundary = this.getBoundary(event);
|
|
281
|
-
const body = event.isBase64Encoded ? Buffer.from(event.body, 'base64').toString('binary').trim() : event.body;
|
|
282
|
-
const result = {};
|
|
283
|
-
body.split(boundary).forEach(item => {
|
|
284
|
-
if (/filename=".+"/g.test(item)) {
|
|
285
|
-
result[item.match(/name=".+";/g)[0].slice(6, -2)] = {
|
|
286
|
-
type: 'file',
|
|
287
|
-
filename: item.match(/filename=".+"/g)[0].slice(10, -1),
|
|
288
|
-
contentType: item.match(/Content-Type:\s.+/g)[0].slice(14),
|
|
289
|
-
content: useBuffer ? Buffer.from(item.slice(item.search(/Content-Type:\s.+/g) + item.match(/Content-Type:\s.+/g)[0].length + 4, -4), 'binary') : item.slice(item.search(/Content-Type:\s.+/g) + item.match(/Content-Type:\s.+/g)[0].length + 4, -4)
|
|
290
|
-
};
|
|
291
|
-
} else if (/name=".+"/g.test(item)) {
|
|
292
|
-
result[item.match(/name=".+"/g)[0].slice(6, -1)] = item.slice(item.search(/name=".+"/g) + item.match(/name=".+"/g)[0].length + 4, -4);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
return result;
|
|
296
|
-
}
|
|
297
|
-
/**
|
|
298
|
-
* Fetch the request AWS event Records
|
|
299
|
-
*
|
|
300
|
-
* @returns {*}
|
|
301
|
-
*/
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
getAWSRecords() {
|
|
305
|
-
const event = this.getContainer().getEvent();
|
|
306
|
-
const eventRecord = event.Records && event.Records[0];
|
|
307
|
-
|
|
308
|
-
if (typeof event.Records !== 'undefined' && typeof event.Records[0] !== 'undefined' && typeof eventRecord.eventSource !== 'undefined') {
|
|
309
|
-
return eventRecord;
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
return null;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Gets a value independently from
|
|
316
|
-
* the case of the key
|
|
317
|
-
*
|
|
318
|
-
* @param object
|
|
319
|
-
* @param key
|
|
320
|
-
*/
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
getValueIgnoringKeyCase(object, key) {
|
|
324
|
-
const foundKey = Object.keys(object).find(currentKey => currentKey.toLocaleLowerCase() === key.toLowerCase());
|
|
325
|
-
return object[foundKey];
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Returns the content type
|
|
329
|
-
* assoiated with the request
|
|
330
|
-
*
|
|
331
|
-
* @param event
|
|
332
|
-
*/
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
getBoundary(event) {
|
|
336
|
-
return this.getValueIgnoringKeyCase(event.headers, 'Content-Type').split('=')[1];
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
exports.default = RequestService;
|