@whook/gcp-functions 8.3.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 (45) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +187 -0
  3. package/dist/commands/testHTTPFunction.d.ts +12 -0
  4. package/dist/commands/testHTTPFunction.js +156 -0
  5. package/dist/commands/testHTTPFunction.js.map +1 -0
  6. package/dist/commands/testHTTPFunction.mjs +136 -0
  7. package/dist/commands/testHTTPFunction.mjs.map +1 -0
  8. package/dist/index.d.ts +18 -0
  9. package/dist/index.js +299 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/index.mjs +265 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/dist/libs/utils.d.ts +5 -0
  14. package/dist/libs/utils.js +39 -0
  15. package/dist/libs/utils.js.map +1 -0
  16. package/dist/libs/utils.mjs +27 -0
  17. package/dist/libs/utils.mjs.map +1 -0
  18. package/dist/services/_autoload.d.ts +17 -0
  19. package/dist/services/_autoload.js +121 -0
  20. package/dist/services/_autoload.js.map +1 -0
  21. package/dist/services/_autoload.mjs +107 -0
  22. package/dist/services/_autoload.mjs.map +1 -0
  23. package/dist/services/log.d.ts +2 -0
  24. package/dist/services/log.js +14 -0
  25. package/dist/services/log.js.map +1 -0
  26. package/dist/services/log.mjs +4 -0
  27. package/dist/services/log.mjs.map +1 -0
  28. package/dist/services/log.test.d.ts +1 -0
  29. package/dist/services/log.test.js +12 -0
  30. package/dist/services/log.test.js.map +1 -0
  31. package/dist/services/log.test.mjs +7 -0
  32. package/dist/services/log.test.mjs.map +1 -0
  33. package/dist/wrappers/googleHTTPFunction.d.ts +22 -0
  34. package/dist/wrappers/googleHTTPFunction.js +310 -0
  35. package/dist/wrappers/googleHTTPFunction.js.map +1 -0
  36. package/dist/wrappers/googleHTTPFunction.mjs +289 -0
  37. package/dist/wrappers/googleHTTPFunction.mjs.map +1 -0
  38. package/package.json +215 -0
  39. package/src/commands/testHTTPFunction.ts +181 -0
  40. package/src/index.ts +443 -0
  41. package/src/libs/utils.ts +43 -0
  42. package/src/services/_autoload.ts +161 -0
  43. package/src/services/log.test.ts +7 -0
  44. package/src/services/log.ts +4 -0
  45. package/src/wrappers/googleHTTPFunction.ts +468 -0
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = wrapHandlerForAWSHTTPFunction;
7
+
8
+ var _httpRouter = require("@whook/http-router");
9
+
10
+ var _knifecycle = require("knifecycle");
11
+
12
+ var _ajv = _interopRequireDefault(require("ajv"));
13
+
14
+ var _ajvFormats = _interopRequireDefault(require("ajv-formats"));
15
+
16
+ var _bytes = _interopRequireDefault(require("bytes"));
17
+
18
+ var _yhttperror = _interopRequireDefault(require("yhttperror"));
19
+
20
+ var _whook = require("@whook/whook");
21
+
22
+ var _cors = require("@whook/cors");
23
+
24
+ var _stream = _interopRequireDefault(require("stream"));
25
+
26
+ const _excluded = ["OPERATION_API", "WRAPPERS", "NODE_ENV", "DEBUG_NODE_ENVS", "DECODERS", "ENCODERS", "log", "time"];
27
+
28
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
+
30
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
31
+
32
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
33
+
34
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
35
+
36
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
37
+
38
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
39
+
40
+ const SEARCH_SEPARATOR = '?';
41
+ const PATH_SEPARATOR = '/';
42
+
43
+ function wrapHandlerForAWSHTTPFunction(initHandler) {
44
+ return (0, _knifecycle.alsoInject)(['OPERATION_API', 'WRAPPERS', '?DEBUG_NODE_ENVS', 'NODE_ENV', '?DECODERS', '?ENCODERS', '?PARSERS', '?STRINGIFYERS', '?BUFFER_LIMIT', 'QUERY_PARSER', 'obfuscator', '?log', '?time'], (0, _knifecycle.reuseSpecialProps)(initHandler, initHandlerForAWSHTTPFunction.bind(null, initHandler)));
45
+ }
46
+
47
+ async function initHandlerForAWSHTTPFunction(initHandler, _ref) {
48
+ let {
49
+ OPERATION_API,
50
+ WRAPPERS,
51
+ NODE_ENV,
52
+ DEBUG_NODE_ENVS = _httpRouter.DEFAULT_DEBUG_NODE_ENVS,
53
+ DECODERS = _httpRouter.DEFAULT_DECODERS,
54
+ ENCODERS = _httpRouter.DEFAULT_ENCODERS,
55
+ log = _whook.noop,
56
+ time = Date.now.bind(Date)
57
+ } = _ref,
58
+ services = _objectWithoutProperties(_ref, _excluded);
59
+
60
+ const path = Object.keys(OPERATION_API.paths)[0];
61
+ const method = Object.keys(OPERATION_API.paths[path])[0];
62
+
63
+ const OPERATION = _objectSpread({
64
+ path,
65
+ method
66
+ }, OPERATION_API.paths[path][method]);
67
+
68
+ const consumableCharsets = Object.keys(DECODERS);
69
+ const produceableCharsets = Object.keys(ENCODERS);
70
+ const consumableMediaTypes = (0, _httpRouter.extractConsumableMediaTypes)(OPERATION);
71
+ const produceableMediaTypes = (0, _httpRouter.extractProduceableMediaTypes)(OPERATION);
72
+ const ajv = new _ajv.default({
73
+ verbose: DEBUG_NODE_ENVS.includes(NODE_ENV),
74
+ strict: true,
75
+ logger: {
76
+ log: (...args) => log('debug', ...args),
77
+ warn: (...args) => log('warning', ...args),
78
+ error: (...args) => log('error', ...args)
79
+ },
80
+ useDefaults: true,
81
+ coerceTypes: true
82
+ });
83
+ (0, _ajvFormats.default)(ajv);
84
+ const ammendedParameters = (0, _httpRouter.extractOperationSecurityParameters)(OPERATION_API, OPERATION);
85
+ const validators = (0, _httpRouter.prepareParametersValidators)(ajv, OPERATION.operationId, (OPERATION.parameters || []).concat(ammendedParameters));
86
+ const bodyValidator = (0, _httpRouter.prepareBodyValidator)(ajv, OPERATION);
87
+ const applyWrappers = (0, _whook.compose)(...WRAPPERS);
88
+ const handler = await applyWrappers(initHandler)(_objectSpread(_objectSpread({
89
+ OPERATION,
90
+ DEBUG_NODE_ENVS,
91
+ NODE_ENV
92
+ }, services), {}, {
93
+ time,
94
+ log
95
+ }));
96
+ return handleForAWSHTTPFunction.bind(null, _objectSpread({
97
+ OPERATION,
98
+ NODE_ENV,
99
+ DEBUG_NODE_ENVS,
100
+ DECODERS,
101
+ ENCODERS,
102
+ log,
103
+ time
104
+ }, services), {
105
+ consumableMediaTypes,
106
+ produceableMediaTypes,
107
+ consumableCharsets,
108
+ produceableCharsets,
109
+ validators,
110
+ bodyValidator,
111
+ ammendedParameters
112
+ }, handler);
113
+ }
114
+
115
+ async function handleForAWSHTTPFunction({
116
+ OPERATION,
117
+ DEBUG_NODE_ENVS,
118
+ NODE_ENV,
119
+ ENCODERS,
120
+ DECODERS,
121
+ PARSERS = _httpRouter.DEFAULT_PARSERS,
122
+ STRINGIFYERS = _httpRouter.DEFAULT_STRINGIFYERS,
123
+ BUFFER_LIMIT = _httpRouter.DEFAULT_BUFFER_LIMIT,
124
+ QUERY_PARSER,
125
+ CORS,
126
+ log,
127
+ obfuscator
128
+ }, {
129
+ consumableMediaTypes,
130
+ produceableMediaTypes,
131
+ consumableCharsets,
132
+ produceableCharsets,
133
+ validators,
134
+ bodyValidator
135
+ }, handler, req, res) {
136
+ const debugging = DEBUG_NODE_ENVS.includes(NODE_ENV);
137
+
138
+ const bufferLimit = _bytes.default.parse(BUFFER_LIMIT);
139
+
140
+ log('info', 'GCP_FUNCTIONS_REQUEST', JSON.stringify({
141
+ url: req.originalUrl,
142
+ method: req.method,
143
+ body: req.body,
144
+ // body: obfuscateEventBody(obfuscator, req.body),
145
+ headers: obfuscator.obfuscateSensibleHeaders(req.headers)
146
+ }));
147
+ const request = await gcpfReqToRequest(req);
148
+ let parameters;
149
+ let response;
150
+ let responseLog;
151
+ let responseSpec;
152
+ log('debug', 'REQUEST', JSON.stringify(_objectSpread(_objectSpread({}, request), {}, {
153
+ body: request.body ? 'Stream' : undefined,
154
+ headers: obfuscator.obfuscateSensibleHeaders(request.headers)
155
+ })));
156
+
157
+ try {
158
+ const operation = OPERATION;
159
+ const bodySpec = (0, _httpRouter.extractBodySpec)(request, consumableMediaTypes, consumableCharsets);
160
+ responseSpec = (0, _httpRouter.extractResponseSpec)(operation, request, produceableMediaTypes, produceableCharsets);
161
+
162
+ try {
163
+ const body = await (0, _httpRouter.getBody)({
164
+ DECODERS,
165
+ PARSERS,
166
+ bufferLimit
167
+ }, operation, request.body, bodySpec);
168
+ const path = request.url.split(SEARCH_SEPARATOR)[0];
169
+ const parts = path.split(PATH_SEPARATOR).filter(_whook.identity);
170
+ const search = request.url.substr(request.url.split(SEARCH_SEPARATOR)[0].length);
171
+ const pathParameters = OPERATION.path.split(PATH_SEPARATOR).filter(_whook.identity).map((part, index) => {
172
+ const matches = /^\{([\d\w]+)\}$/i.exec(part);
173
+
174
+ if (matches) {
175
+ return {
176
+ name: matches[1],
177
+ value: parts[index]
178
+ };
179
+ }
180
+ }).filter(_whook.identity).reduce((accParameters, {
181
+ name,
182
+ value
183
+ }) => _objectSpread(_objectSpread({}, accParameters), {}, {
184
+ [name]: value
185
+ }), {}); // TODO: Update strictQS to handle OpenAPI 3
186
+
187
+ const retroCompatibleQueryParameters = (OPERATION.parameters || []).filter(p => p.in === 'query').map(p => _objectSpread(_objectSpread({}, p), p.schema));
188
+ parameters = _objectSpread(_objectSpread(_objectSpread({}, pathParameters), QUERY_PARSER(retroCompatibleQueryParameters, search)), (0, _httpRouter.filterHeaders)(operation.parameters, request.headers));
189
+ parameters = _objectSpread({
190
+ // TODO: Use the security of the operation to infer
191
+ // authorization parameters, see:
192
+ // https://github.com/nfroidure/whook/blob/06ccae93d1d52d97ff70fd5e19fa826bdabf3968/packages/whook-http-router/src/validation.js#L110
193
+ authorization: parameters.authorization
194
+ }, (0, _httpRouter.castParameters)(operation.parameters || [], parameters));
195
+ (0, _httpRouter.applyValidators)(operation, validators, parameters);
196
+ bodyValidator(operation, bodySpec.contentType, body);
197
+ parameters = _objectSpread(_objectSpread({}, parameters), 'undefined' !== typeof body ? {
198
+ body
199
+ } : {});
200
+ } catch (err) {
201
+ throw _yhttperror.default.cast(err, 400);
202
+ }
203
+
204
+ response = await (0, _httpRouter.executeHandler)(operation, handler, parameters);
205
+
206
+ if (response.body) {
207
+ response.headers['content-type'] = response.headers['content-type'] || responseSpec.contentTypes[0];
208
+ } // Check the stringifyer only when a schema is
209
+ // specified and it is not a binary one
210
+
211
+
212
+ const responseObject = operation.responses && operation.responses[response.status];
213
+ const responseSchema = responseObject && responseObject.content && responseObject.content[response.headers['content-type']] && responseObject.content[response.headers['content-type']].schema;
214
+ const responseHasSchema = responseSchema && (responseSchema.type !== 'string' || responseSchema.format !== 'binary');
215
+
216
+ if (responseHasSchema && !STRINGIFYERS[response.headers['content-type']]) {
217
+ throw new _yhttperror.default(500, 'E_STRINGIFYER_LACK', response.headers['content-type']);
218
+ }
219
+
220
+ if (response.body) {
221
+ (0, _httpRouter.checkResponseMediaType)(request, responseSpec, produceableMediaTypes);
222
+ (0, _httpRouter.checkResponseCharset)(request, responseSpec, produceableCharsets);
223
+ }
224
+
225
+ responseLog = {
226
+ type: 'success',
227
+ status: response.status
228
+ };
229
+ log('debug', JSON.stringify(responseLog));
230
+ } catch (err) {
231
+ var _castedError$headers;
232
+
233
+ const castedError = _yhttperror.default.cast(err);
234
+
235
+ responseLog = {
236
+ type: 'error',
237
+ code: castedError.code,
238
+ statusCode: castedError.httpCode,
239
+ params: castedError.params || [],
240
+ stack: castedError.stack
241
+ };
242
+ log('error', JSON.stringify(responseLog));
243
+ response = {
244
+ status: castedError.httpCode,
245
+ headers: _objectSpread(_objectSpread(_objectSpread({}, (0, _cors.lowerCaseHeaders)(CORS)), (_castedError$headers = castedError.headers) !== null && _castedError$headers !== void 0 ? _castedError$headers : {}), {}, {
246
+ 'content-type': 'application/json'
247
+ }),
248
+ body: {
249
+ error: {
250
+ code: castedError.code,
251
+ stack: debugging ? responseLog.stack : undefined,
252
+ params: debugging ? responseLog.params : undefined
253
+ }
254
+ }
255
+ };
256
+ }
257
+
258
+ log('debug', 'RESPONSE', JSON.stringify(_objectSpread(_objectSpread({}, response), {}, {
259
+ body: obfuscateEventBody(obfuscator, response.body),
260
+ headers: obfuscator.obfuscateSensibleHeaders(response.headers)
261
+ })));
262
+ await pipeResponseInGCPFResponse(await (0, _httpRouter.sendBody)({
263
+ ENCODERS,
264
+ STRINGIFYERS
265
+ }, response), res);
266
+ }
267
+
268
+ async function gcpfReqToRequest(req) {
269
+ const request = {
270
+ method: req.method.toLowerCase(),
271
+ headers: (0, _cors.lowerCaseHeaders)(req.headers || {}),
272
+ url: req.originalUrl
273
+ };
274
+
275
+ if (req.rawBody) {
276
+ request.headers['content-length'] = req.rawBody.length.toString();
277
+ const bodyStream = new _stream.default.PassThrough();
278
+ request.body = bodyStream;
279
+ bodyStream.write(req.rawBody);
280
+ bodyStream.end();
281
+ }
282
+
283
+ return request;
284
+ }
285
+
286
+ async function pipeResponseInGCPFResponse(response, res) {
287
+ Object.keys(response.headers).forEach(headerName => {
288
+ res.set(headerName, response.headers[headerName]);
289
+ });
290
+ res.status(response.status);
291
+
292
+ if (response.body) {
293
+ response.body.pipe(res);
294
+ return;
295
+ }
296
+
297
+ res.end();
298
+ }
299
+
300
+ function obfuscateEventBody(obfuscator, rawBody) {
301
+ if (typeof rawBody === 'string') {
302
+ try {
303
+ const jsonBody = JSON.parse(rawBody);
304
+ return JSON.stringify(obfuscator.obfuscateSensibleProps(jsonBody)); // eslint-disable-next-line
305
+ } catch (err) {}
306
+ }
307
+
308
+ return rawBody;
309
+ }
310
+ //# sourceMappingURL=googleHTTPFunction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/wrappers/googleHTTPFunction.ts"],"names":["SEARCH_SEPARATOR","PATH_SEPARATOR","wrapHandlerForAWSHTTPFunction","initHandler","initHandlerForAWSHTTPFunction","bind","OPERATION_API","WRAPPERS","NODE_ENV","DEBUG_NODE_ENVS","DEFAULT_DEBUG_NODE_ENVS","DECODERS","DEFAULT_DECODERS","ENCODERS","DEFAULT_ENCODERS","log","noop","time","Date","now","services","path","Object","keys","paths","method","OPERATION","consumableCharsets","produceableCharsets","consumableMediaTypes","produceableMediaTypes","ajv","Ajv","verbose","includes","strict","logger","args","warn","error","useDefaults","coerceTypes","ammendedParameters","validators","operationId","parameters","concat","bodyValidator","applyWrappers","handler","handleForAWSHTTPFunction","PARSERS","DEFAULT_PARSERS","STRINGIFYERS","DEFAULT_STRINGIFYERS","BUFFER_LIMIT","DEFAULT_BUFFER_LIMIT","QUERY_PARSER","CORS","obfuscator","req","res","debugging","bufferLimit","bytes","parse","JSON","stringify","url","originalUrl","body","headers","obfuscateSensibleHeaders","request","gcpfReqToRequest","response","responseLog","responseSpec","undefined","operation","bodySpec","split","parts","filter","identity","search","substr","length","pathParameters","map","part","index","matches","exec","name","value","reduce","accParameters","retroCompatibleQueryParameters","p","in","schema","authorization","contentType","err","HTTPError","cast","contentTypes","responseObject","responses","status","responseSchema","content","responseHasSchema","type","format","castedError","code","statusCode","httpCode","params","stack","obfuscateEventBody","pipeResponseInGCPFResponse","toLowerCase","rawBody","toString","bodyStream","stream","PassThrough","write","end","forEach","headerName","set","pipe","jsonBody","obfuscateSensibleProps"],"mappings":"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","sourcesContent":["import {\n DEFAULT_DEBUG_NODE_ENVS,\n DEFAULT_BUFFER_LIMIT,\n DEFAULT_PARSERS,\n DEFAULT_STRINGIFYERS,\n DEFAULT_DECODERS,\n DEFAULT_ENCODERS,\n extractOperationSecurityParameters,\n castParameters,\n} from '@whook/http-router';\nimport { reuseSpecialProps, alsoInject } from 'knifecycle';\nimport Ajv from 'ajv';\nimport addAJVFormats from 'ajv-formats';\nimport bytes from 'bytes';\nimport HTTPError from 'yhttperror';\nimport {\n prepareParametersValidators,\n prepareBodyValidator,\n applyValidators,\n filterHeaders,\n extractBodySpec,\n extractResponseSpec,\n checkResponseCharset,\n checkResponseMediaType,\n executeHandler,\n extractProduceableMediaTypes,\n extractConsumableMediaTypes,\n getBody,\n sendBody,\n} from '@whook/http-router';\nimport { noop, compose, identity } from '@whook/whook';\nimport { lowerCaseHeaders } from '@whook/cors';\nimport stream from 'stream';\nimport type { WhookQueryStringParser } from '@whook/http-router';\nimport type { ServiceInitializer, Dependencies, Service } from 'knifecycle';\nimport type {\n WhookRequest,\n WhookResponse,\n WhookHandler,\n ObfuscatorService,\n WhookOperation,\n WhookWrapper,\n} from '@whook/whook';\nimport type { TimeService, LogService } from 'common-services';\nimport type { OpenAPIV3 } from 'openapi-types';\nimport type { Readable } from 'stream';\nimport type { CORSConfig } from '@whook/cors';\n\ntype HTTPWrapperDependencies = {\n NODE_ENV: string;\n DEBUG_NODE_ENVS?: string[];\n OPERATION: WhookOperation;\n DECODERS?: typeof DEFAULT_DECODERS;\n ENCODERS?: typeof DEFAULT_ENCODERS;\n PARSERS?: typeof DEFAULT_PARSERS;\n STRINGIFYERS?: typeof DEFAULT_STRINGIFYERS;\n QUERY_PARSER: WhookQueryStringParser;\n BUFFER_LIMIT?: string;\n obfuscator: ObfuscatorService;\n time?: TimeService;\n log?: LogService;\n WRAPPERS: WhookWrapper<Dependencies, Service>[];\n};\n\nconst SEARCH_SEPARATOR = '?';\nconst PATH_SEPARATOR = '/';\n\nexport default function wrapHandlerForAWSHTTPFunction<\n D,\n S extends WhookHandler,\n>(\n initHandler: ServiceInitializer<D, S>,\n): ServiceInitializer<D & HTTPWrapperDependencies, S> {\n return alsoInject<HTTPWrapperDependencies, D, S>(\n [\n 'OPERATION_API',\n 'WRAPPERS',\n '?DEBUG_NODE_ENVS',\n 'NODE_ENV',\n '?DECODERS',\n '?ENCODERS',\n '?PARSERS',\n '?STRINGIFYERS',\n '?BUFFER_LIMIT',\n 'QUERY_PARSER',\n 'obfuscator',\n '?log',\n '?time',\n ],\n reuseSpecialProps(\n initHandler,\n initHandlerForAWSHTTPFunction.bind(\n null,\n initHandler,\n ) as ServiceInitializer<D, S>,\n ),\n );\n}\n\nasync function initHandlerForAWSHTTPFunction(\n initHandler: ServiceInitializer<unknown, WhookHandler>,\n {\n OPERATION_API,\n WRAPPERS,\n NODE_ENV,\n DEBUG_NODE_ENVS = DEFAULT_DEBUG_NODE_ENVS,\n DECODERS = DEFAULT_DECODERS,\n ENCODERS = DEFAULT_ENCODERS,\n log = noop,\n time = Date.now.bind(Date),\n ...services\n },\n) {\n const path = Object.keys(OPERATION_API.paths)[0];\n const method = Object.keys(OPERATION_API.paths[path])[0];\n const OPERATION: WhookOperation = {\n path,\n method,\n ...OPERATION_API.paths[path][method],\n };\n const consumableCharsets = Object.keys(DECODERS);\n const produceableCharsets = Object.keys(ENCODERS);\n const consumableMediaTypes = extractConsumableMediaTypes(OPERATION);\n const produceableMediaTypes = extractProduceableMediaTypes(OPERATION);\n const ajv = new Ajv({\n verbose: DEBUG_NODE_ENVS.includes(NODE_ENV),\n strict: true,\n logger: {\n log: (...args) => log('debug', ...args),\n warn: (...args) => log('warning', ...args),\n error: (...args) => log('error', ...args),\n },\n useDefaults: true,\n coerceTypes: true,\n });\n addAJVFormats(ajv);\n const ammendedParameters = extractOperationSecurityParameters(\n OPERATION_API,\n OPERATION,\n );\n const validators = prepareParametersValidators(\n ajv,\n OPERATION.operationId,\n ((OPERATION.parameters || []) as OpenAPIV3.ParameterObject[]).concat(\n ammendedParameters,\n ),\n );\n const bodyValidator = prepareBodyValidator(ajv, OPERATION);\n const applyWrappers = compose(...WRAPPERS) as WhookWrapper<\n Dependencies,\n Service\n >;\n\n const handler = await (\n applyWrappers(initHandler) as ServiceInitializer<Dependencies, Service>\n )({\n OPERATION,\n DEBUG_NODE_ENVS,\n NODE_ENV,\n ...services,\n time,\n log,\n });\n\n return handleForAWSHTTPFunction.bind(\n null,\n {\n OPERATION,\n NODE_ENV,\n DEBUG_NODE_ENVS,\n DECODERS,\n ENCODERS,\n log,\n time,\n ...services,\n },\n {\n consumableMediaTypes,\n produceableMediaTypes,\n consumableCharsets,\n produceableCharsets,\n validators,\n bodyValidator,\n ammendedParameters,\n },\n handler,\n );\n}\n\nasync function handleForAWSHTTPFunction(\n {\n OPERATION,\n DEBUG_NODE_ENVS,\n NODE_ENV,\n ENCODERS,\n DECODERS,\n PARSERS = DEFAULT_PARSERS,\n STRINGIFYERS = DEFAULT_STRINGIFYERS,\n BUFFER_LIMIT = DEFAULT_BUFFER_LIMIT,\n QUERY_PARSER,\n CORS,\n log,\n obfuscator,\n }: HTTPWrapperDependencies & { CORS: CORSConfig },\n {\n consumableMediaTypes,\n produceableMediaTypes,\n consumableCharsets,\n produceableCharsets,\n validators,\n bodyValidator,\n },\n handler: WhookHandler,\n req,\n res,\n) {\n const debugging = DEBUG_NODE_ENVS.includes(NODE_ENV);\n const bufferLimit = bytes.parse(BUFFER_LIMIT);\n\n log(\n 'info',\n 'GCP_FUNCTIONS_REQUEST',\n JSON.stringify({\n url: req.originalUrl,\n method: req.method,\n body: req.body,\n // body: obfuscateEventBody(obfuscator, req.body),\n headers: obfuscator.obfuscateSensibleHeaders(req.headers),\n }),\n );\n\n const request = await gcpfReqToRequest(req);\n let parameters;\n let response;\n let responseLog;\n let responseSpec;\n\n log(\n 'debug',\n 'REQUEST',\n JSON.stringify({\n ...request,\n body: request.body ? 'Stream' : undefined,\n headers: obfuscator.obfuscateSensibleHeaders(request.headers),\n }),\n );\n\n try {\n const operation = OPERATION;\n const bodySpec = extractBodySpec(\n request,\n consumableMediaTypes,\n consumableCharsets,\n );\n\n responseSpec = extractResponseSpec(\n operation,\n request,\n produceableMediaTypes,\n produceableCharsets,\n );\n\n try {\n const body = await getBody(\n {\n DECODERS,\n PARSERS,\n bufferLimit,\n },\n operation,\n request.body as Readable,\n bodySpec,\n );\n const path = request.url.split(SEARCH_SEPARATOR)[0];\n const parts = path.split(PATH_SEPARATOR).filter(identity);\n const search = request.url.substr(\n request.url.split(SEARCH_SEPARATOR)[0].length,\n );\n\n const pathParameters = OPERATION.path\n .split(PATH_SEPARATOR)\n .filter(identity)\n .map((part, index) => {\n const matches = /^\\{([\\d\\w]+)\\}$/i.exec(part);\n\n if (matches) {\n return {\n name: matches[1],\n value: parts[index],\n };\n }\n })\n .filter(identity)\n .reduce(\n (accParameters, { name, value }) => ({\n ...accParameters,\n [name]: value,\n }),\n {},\n );\n\n // TODO: Update strictQS to handle OpenAPI 3\n const retroCompatibleQueryParameters = (OPERATION.parameters || [])\n .filter((p) => p.in === 'query')\n .map((p) => ({ ...p, ...p.schema }));\n\n parameters = {\n ...pathParameters,\n ...QUERY_PARSER(retroCompatibleQueryParameters as any, search),\n ...filterHeaders(operation.parameters, request.headers),\n };\n\n parameters = {\n // TODO: Use the security of the operation to infer\n // authorization parameters, see:\n // https://github.com/nfroidure/whook/blob/06ccae93d1d52d97ff70fd5e19fa826bdabf3968/packages/whook-http-router/src/validation.js#L110\n authorization: parameters.authorization,\n ...castParameters(operation.parameters || [], parameters),\n };\n\n applyValidators(operation, validators, parameters);\n\n bodyValidator(operation, bodySpec.contentType, body);\n\n parameters = {\n ...parameters,\n ...('undefined' !== typeof body ? { body } : {}),\n };\n } catch (err) {\n throw HTTPError.cast(err, 400);\n }\n\n response = await executeHandler(operation, handler, parameters);\n\n if (response.body) {\n response.headers['content-type'] =\n response.headers['content-type'] || responseSpec.contentTypes[0];\n }\n\n // Check the stringifyer only when a schema is\n // specified and it is not a binary one\n const responseObject =\n operation.responses &&\n (operation.responses[response.status] as OpenAPIV3.ResponseObject);\n const responseSchema =\n responseObject &&\n responseObject.content &&\n responseObject.content[response.headers['content-type']] &&\n (responseObject.content[response.headers['content-type']]\n .schema as OpenAPIV3.SchemaObject);\n const responseHasSchema =\n responseSchema &&\n (responseSchema.type !== 'string' || responseSchema.format !== 'binary');\n\n if (responseHasSchema && !STRINGIFYERS[response.headers['content-type']]) {\n throw new HTTPError(\n 500,\n 'E_STRINGIFYER_LACK',\n response.headers['content-type'],\n );\n }\n if (response.body) {\n checkResponseMediaType(request, responseSpec, produceableMediaTypes);\n checkResponseCharset(request, responseSpec, produceableCharsets);\n }\n responseLog = {\n type: 'success',\n status: response.status,\n };\n log('debug', JSON.stringify(responseLog));\n } catch (err) {\n const castedError = HTTPError.cast(err);\n\n responseLog = {\n type: 'error',\n code: castedError.code,\n statusCode: castedError.httpCode,\n params: castedError.params || [],\n stack: castedError.stack,\n };\n\n log('error', JSON.stringify(responseLog));\n response = {\n status: castedError.httpCode,\n headers: {\n ...lowerCaseHeaders(CORS),\n ...(castedError.headers ?? {}),\n 'content-type': 'application/json',\n },\n body: {\n error: {\n code: castedError.code,\n stack: debugging ? responseLog.stack : undefined,\n params: debugging ? responseLog.params : undefined,\n },\n },\n };\n }\n\n log(\n 'debug',\n 'RESPONSE',\n JSON.stringify({\n ...response,\n body: obfuscateEventBody(obfuscator, response.body),\n headers: obfuscator.obfuscateSensibleHeaders(response.headers),\n }),\n );\n\n await pipeResponseInGCPFResponse(\n await sendBody(\n {\n ENCODERS,\n STRINGIFYERS,\n },\n response,\n ),\n res,\n );\n}\n\nasync function gcpfReqToRequest(req): Promise<WhookRequest> {\n const request: WhookRequest = {\n method: req.method.toLowerCase(),\n headers: lowerCaseHeaders(req.headers || {}),\n url: req.originalUrl,\n };\n\n if (req.rawBody) {\n request.headers['content-length'] = req.rawBody.length.toString();\n const bodyStream = new stream.PassThrough();\n\n request.body = bodyStream;\n bodyStream.write(req.rawBody);\n bodyStream.end();\n }\n\n return request;\n}\n\nasync function pipeResponseInGCPFResponse(\n response: WhookResponse,\n res,\n): Promise<void> {\n Object.keys(response.headers).forEach((headerName) => {\n res.set(headerName, response.headers[headerName]);\n });\n res.status(response.status);\n\n if (response.body) {\n (response.body as Readable).pipe(res);\n return;\n }\n\n res.end();\n}\n\nfunction obfuscateEventBody(obfuscator, rawBody) {\n if (typeof rawBody === 'string') {\n try {\n const jsonBody = JSON.parse(rawBody);\n\n return JSON.stringify(obfuscator.obfuscateSensibleProps(jsonBody));\n // eslint-disable-next-line\n } catch (err) {}\n }\n return rawBody;\n}\n"],"file":"googleHTTPFunction.js"}
@@ -0,0 +1,289 @@
1
+ const _excluded = ["OPERATION_API", "WRAPPERS", "NODE_ENV", "DEBUG_NODE_ENVS", "DECODERS", "ENCODERS", "log", "time"];
2
+
3
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }
4
+
5
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
6
+
7
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
8
+
9
+ function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
10
+
11
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
12
+
13
+ import { DEFAULT_DEBUG_NODE_ENVS, DEFAULT_BUFFER_LIMIT, DEFAULT_PARSERS, DEFAULT_STRINGIFYERS, DEFAULT_DECODERS, DEFAULT_ENCODERS, extractOperationSecurityParameters, castParameters } from '@whook/http-router';
14
+ import { reuseSpecialProps, alsoInject } from 'knifecycle';
15
+ import Ajv from 'ajv';
16
+ import addAJVFormats from 'ajv-formats';
17
+ import bytes from 'bytes';
18
+ import HTTPError from 'yhttperror';
19
+ import { prepareParametersValidators, prepareBodyValidator, applyValidators, filterHeaders, extractBodySpec, extractResponseSpec, checkResponseCharset, checkResponseMediaType, executeHandler, extractProduceableMediaTypes, extractConsumableMediaTypes, getBody, sendBody } from '@whook/http-router';
20
+ import { noop, compose, identity } from '@whook/whook';
21
+ import { lowerCaseHeaders } from '@whook/cors';
22
+ import stream from 'stream';
23
+ const SEARCH_SEPARATOR = '?';
24
+ const PATH_SEPARATOR = '/';
25
+ export default function wrapHandlerForAWSHTTPFunction(initHandler) {
26
+ return alsoInject(['OPERATION_API', 'WRAPPERS', '?DEBUG_NODE_ENVS', 'NODE_ENV', '?DECODERS', '?ENCODERS', '?PARSERS', '?STRINGIFYERS', '?BUFFER_LIMIT', 'QUERY_PARSER', 'obfuscator', '?log', '?time'], reuseSpecialProps(initHandler, initHandlerForAWSHTTPFunction.bind(null, initHandler)));
27
+ }
28
+
29
+ async function initHandlerForAWSHTTPFunction(initHandler, _ref) {
30
+ let {
31
+ OPERATION_API,
32
+ WRAPPERS,
33
+ NODE_ENV,
34
+ DEBUG_NODE_ENVS = DEFAULT_DEBUG_NODE_ENVS,
35
+ DECODERS = DEFAULT_DECODERS,
36
+ ENCODERS = DEFAULT_ENCODERS,
37
+ log = noop,
38
+ time = Date.now.bind(Date)
39
+ } = _ref,
40
+ services = _objectWithoutProperties(_ref, _excluded);
41
+
42
+ const path = Object.keys(OPERATION_API.paths)[0];
43
+ const method = Object.keys(OPERATION_API.paths[path])[0];
44
+
45
+ const OPERATION = _objectSpread({
46
+ path,
47
+ method
48
+ }, OPERATION_API.paths[path][method]);
49
+
50
+ const consumableCharsets = Object.keys(DECODERS);
51
+ const produceableCharsets = Object.keys(ENCODERS);
52
+ const consumableMediaTypes = extractConsumableMediaTypes(OPERATION);
53
+ const produceableMediaTypes = extractProduceableMediaTypes(OPERATION);
54
+ const ajv = new Ajv({
55
+ verbose: DEBUG_NODE_ENVS.includes(NODE_ENV),
56
+ strict: true,
57
+ logger: {
58
+ log: (...args) => log('debug', ...args),
59
+ warn: (...args) => log('warning', ...args),
60
+ error: (...args) => log('error', ...args)
61
+ },
62
+ useDefaults: true,
63
+ coerceTypes: true
64
+ });
65
+ addAJVFormats(ajv);
66
+ const ammendedParameters = extractOperationSecurityParameters(OPERATION_API, OPERATION);
67
+ const validators = prepareParametersValidators(ajv, OPERATION.operationId, (OPERATION.parameters || []).concat(ammendedParameters));
68
+ const bodyValidator = prepareBodyValidator(ajv, OPERATION);
69
+ const applyWrappers = compose(...WRAPPERS);
70
+ const handler = await applyWrappers(initHandler)(_objectSpread(_objectSpread({
71
+ OPERATION,
72
+ DEBUG_NODE_ENVS,
73
+ NODE_ENV
74
+ }, services), {}, {
75
+ time,
76
+ log
77
+ }));
78
+ return handleForAWSHTTPFunction.bind(null, _objectSpread({
79
+ OPERATION,
80
+ NODE_ENV,
81
+ DEBUG_NODE_ENVS,
82
+ DECODERS,
83
+ ENCODERS,
84
+ log,
85
+ time
86
+ }, services), {
87
+ consumableMediaTypes,
88
+ produceableMediaTypes,
89
+ consumableCharsets,
90
+ produceableCharsets,
91
+ validators,
92
+ bodyValidator,
93
+ ammendedParameters
94
+ }, handler);
95
+ }
96
+
97
+ async function handleForAWSHTTPFunction({
98
+ OPERATION,
99
+ DEBUG_NODE_ENVS,
100
+ NODE_ENV,
101
+ ENCODERS,
102
+ DECODERS,
103
+ PARSERS = DEFAULT_PARSERS,
104
+ STRINGIFYERS = DEFAULT_STRINGIFYERS,
105
+ BUFFER_LIMIT = DEFAULT_BUFFER_LIMIT,
106
+ QUERY_PARSER,
107
+ CORS,
108
+ log,
109
+ obfuscator
110
+ }, {
111
+ consumableMediaTypes,
112
+ produceableMediaTypes,
113
+ consumableCharsets,
114
+ produceableCharsets,
115
+ validators,
116
+ bodyValidator
117
+ }, handler, req, res) {
118
+ const debugging = DEBUG_NODE_ENVS.includes(NODE_ENV);
119
+ const bufferLimit = bytes.parse(BUFFER_LIMIT);
120
+ log('info', 'GCP_FUNCTIONS_REQUEST', JSON.stringify({
121
+ url: req.originalUrl,
122
+ method: req.method,
123
+ body: req.body,
124
+ // body: obfuscateEventBody(obfuscator, req.body),
125
+ headers: obfuscator.obfuscateSensibleHeaders(req.headers)
126
+ }));
127
+ const request = await gcpfReqToRequest(req);
128
+ let parameters;
129
+ let response;
130
+ let responseLog;
131
+ let responseSpec;
132
+ log('debug', 'REQUEST', JSON.stringify(_objectSpread(_objectSpread({}, request), {}, {
133
+ body: request.body ? 'Stream' : undefined,
134
+ headers: obfuscator.obfuscateSensibleHeaders(request.headers)
135
+ })));
136
+
137
+ try {
138
+ const operation = OPERATION;
139
+ const bodySpec = extractBodySpec(request, consumableMediaTypes, consumableCharsets);
140
+ responseSpec = extractResponseSpec(operation, request, produceableMediaTypes, produceableCharsets);
141
+
142
+ try {
143
+ const body = await getBody({
144
+ DECODERS,
145
+ PARSERS,
146
+ bufferLimit
147
+ }, operation, request.body, bodySpec);
148
+ const path = request.url.split(SEARCH_SEPARATOR)[0];
149
+ const parts = path.split(PATH_SEPARATOR).filter(identity);
150
+ const search = request.url.substr(request.url.split(SEARCH_SEPARATOR)[0].length);
151
+ const pathParameters = OPERATION.path.split(PATH_SEPARATOR).filter(identity).map((part, index) => {
152
+ const matches = /^\{([\d\w]+)\}$/i.exec(part);
153
+
154
+ if (matches) {
155
+ return {
156
+ name: matches[1],
157
+ value: parts[index]
158
+ };
159
+ }
160
+ }).filter(identity).reduce((accParameters, {
161
+ name,
162
+ value
163
+ }) => _objectSpread(_objectSpread({}, accParameters), {}, {
164
+ [name]: value
165
+ }), {}); // TODO: Update strictQS to handle OpenAPI 3
166
+
167
+ const retroCompatibleQueryParameters = (OPERATION.parameters || []).filter(p => p.in === 'query').map(p => _objectSpread(_objectSpread({}, p), p.schema));
168
+ parameters = _objectSpread(_objectSpread(_objectSpread({}, pathParameters), QUERY_PARSER(retroCompatibleQueryParameters, search)), filterHeaders(operation.parameters, request.headers));
169
+ parameters = _objectSpread({
170
+ // TODO: Use the security of the operation to infer
171
+ // authorization parameters, see:
172
+ // https://github.com/nfroidure/whook/blob/06ccae93d1d52d97ff70fd5e19fa826bdabf3968/packages/whook-http-router/src/validation.js#L110
173
+ authorization: parameters.authorization
174
+ }, castParameters(operation.parameters || [], parameters));
175
+ applyValidators(operation, validators, parameters);
176
+ bodyValidator(operation, bodySpec.contentType, body);
177
+ parameters = _objectSpread(_objectSpread({}, parameters), 'undefined' !== typeof body ? {
178
+ body
179
+ } : {});
180
+ } catch (err) {
181
+ throw HTTPError.cast(err, 400);
182
+ }
183
+
184
+ response = await executeHandler(operation, handler, parameters);
185
+
186
+ if (response.body) {
187
+ response.headers['content-type'] = response.headers['content-type'] || responseSpec.contentTypes[0];
188
+ } // Check the stringifyer only when a schema is
189
+ // specified and it is not a binary one
190
+
191
+
192
+ const responseObject = operation.responses && operation.responses[response.status];
193
+ const responseSchema = responseObject && responseObject.content && responseObject.content[response.headers['content-type']] && responseObject.content[response.headers['content-type']].schema;
194
+ const responseHasSchema = responseSchema && (responseSchema.type !== 'string' || responseSchema.format !== 'binary');
195
+
196
+ if (responseHasSchema && !STRINGIFYERS[response.headers['content-type']]) {
197
+ throw new HTTPError(500, 'E_STRINGIFYER_LACK', response.headers['content-type']);
198
+ }
199
+
200
+ if (response.body) {
201
+ checkResponseMediaType(request, responseSpec, produceableMediaTypes);
202
+ checkResponseCharset(request, responseSpec, produceableCharsets);
203
+ }
204
+
205
+ responseLog = {
206
+ type: 'success',
207
+ status: response.status
208
+ };
209
+ log('debug', JSON.stringify(responseLog));
210
+ } catch (err) {
211
+ var _castedError$headers;
212
+
213
+ const castedError = HTTPError.cast(err);
214
+ responseLog = {
215
+ type: 'error',
216
+ code: castedError.code,
217
+ statusCode: castedError.httpCode,
218
+ params: castedError.params || [],
219
+ stack: castedError.stack
220
+ };
221
+ log('error', JSON.stringify(responseLog));
222
+ response = {
223
+ status: castedError.httpCode,
224
+ headers: _objectSpread(_objectSpread(_objectSpread({}, lowerCaseHeaders(CORS)), (_castedError$headers = castedError.headers) !== null && _castedError$headers !== void 0 ? _castedError$headers : {}), {}, {
225
+ 'content-type': 'application/json'
226
+ }),
227
+ body: {
228
+ error: {
229
+ code: castedError.code,
230
+ stack: debugging ? responseLog.stack : undefined,
231
+ params: debugging ? responseLog.params : undefined
232
+ }
233
+ }
234
+ };
235
+ }
236
+
237
+ log('debug', 'RESPONSE', JSON.stringify(_objectSpread(_objectSpread({}, response), {}, {
238
+ body: obfuscateEventBody(obfuscator, response.body),
239
+ headers: obfuscator.obfuscateSensibleHeaders(response.headers)
240
+ })));
241
+ await pipeResponseInGCPFResponse(await sendBody({
242
+ ENCODERS,
243
+ STRINGIFYERS
244
+ }, response), res);
245
+ }
246
+
247
+ async function gcpfReqToRequest(req) {
248
+ const request = {
249
+ method: req.method.toLowerCase(),
250
+ headers: lowerCaseHeaders(req.headers || {}),
251
+ url: req.originalUrl
252
+ };
253
+
254
+ if (req.rawBody) {
255
+ request.headers['content-length'] = req.rawBody.length.toString();
256
+ const bodyStream = new stream.PassThrough();
257
+ request.body = bodyStream;
258
+ bodyStream.write(req.rawBody);
259
+ bodyStream.end();
260
+ }
261
+
262
+ return request;
263
+ }
264
+
265
+ async function pipeResponseInGCPFResponse(response, res) {
266
+ Object.keys(response.headers).forEach(headerName => {
267
+ res.set(headerName, response.headers[headerName]);
268
+ });
269
+ res.status(response.status);
270
+
271
+ if (response.body) {
272
+ response.body.pipe(res);
273
+ return;
274
+ }
275
+
276
+ res.end();
277
+ }
278
+
279
+ function obfuscateEventBody(obfuscator, rawBody) {
280
+ if (typeof rawBody === 'string') {
281
+ try {
282
+ const jsonBody = JSON.parse(rawBody);
283
+ return JSON.stringify(obfuscator.obfuscateSensibleProps(jsonBody)); // eslint-disable-next-line
284
+ } catch (err) {}
285
+ }
286
+
287
+ return rawBody;
288
+ }
289
+ //# sourceMappingURL=googleHTTPFunction.mjs.map