@jaypie/express 1.2.4-rc9 → 1.2.4
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/dist/cjs/adapter/LambdaResponseBuffered.d.ts +8 -0
- package/dist/cjs/adapter/LambdaResponseStreaming.d.ts +8 -2
- package/dist/cjs/adapter/__tests__/debug-harness.d.ts +1 -0
- package/dist/cjs/expressStreamHandler.d.ts +2 -0
- package/dist/cjs/getCurrentInvokeUuid.adapter.d.ts +2 -2
- package/dist/cjs/index.cjs +298 -208
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +0 -2
- package/dist/esm/adapter/LambdaResponseBuffered.d.ts +8 -0
- package/dist/esm/adapter/LambdaResponseStreaming.d.ts +8 -2
- package/dist/esm/adapter/__tests__/debug-harness.d.ts +1 -0
- package/dist/esm/expressStreamHandler.d.ts +2 -0
- package/dist/esm/getCurrentInvokeUuid.adapter.d.ts +2 -2
- package/dist/esm/index.d.ts +0 -2
- package/dist/esm/index.js +298 -207
- package/dist/esm/index.js.map +1 -1
- package/package.json +12 -16
- package/dist/cjs/createServer.d.ts +0 -60
- package/dist/cjs/getCurrentInvokeUuid.webadapter.d.ts +0 -12
- package/dist/esm/createServer.d.ts +0 -60
- package/dist/esm/getCurrentInvokeUuid.webadapter.d.ts +0 -12
package/dist/esm/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { ServerResponse } from 'node:http';
|
|
|
3
3
|
import { CorsError, BadRequestError, UnhandledError, GatewayTimeoutError, UnavailableError, BadGatewayError, InternalError, TeapotError, GoneError, MethodNotAllowedError, NotFoundError, ForbiddenError, UnauthorizedError, NotImplementedError } from '@jaypie/errors';
|
|
4
4
|
import { force, envBoolean, JAYPIE, HTTP, getHeaderFrom, jaypieHandler } from '@jaypie/kit';
|
|
5
5
|
import expressCors from 'cors';
|
|
6
|
+
import { loadEnvSecrets, getContentTypeForFormat, formatStreamError } from '@jaypie/aws';
|
|
6
7
|
import { log } from '@jaypie/logger';
|
|
7
|
-
import { loadEnvSecrets } from '@jaypie/aws';
|
|
8
8
|
import { hasDatadogEnv, submitMetric, DATADOG } from '@jaypie/datadog';
|
|
9
9
|
|
|
10
10
|
//
|
|
@@ -32,6 +32,15 @@ class LambdaRequest extends Readable {
|
|
|
32
32
|
this.path = options.url.split("?")[0];
|
|
33
33
|
this.headers = this.normalizeHeaders(options.headers);
|
|
34
34
|
this.bodyBuffer = options.body ?? null;
|
|
35
|
+
// Parse query string from URL
|
|
36
|
+
const queryIndex = options.url.indexOf("?");
|
|
37
|
+
if (queryIndex !== -1) {
|
|
38
|
+
const queryString = options.url.slice(queryIndex + 1);
|
|
39
|
+
const params = new URLSearchParams(queryString);
|
|
40
|
+
for (const [key, value] of params) {
|
|
41
|
+
this.query[key] = value;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
35
44
|
// Store Lambda context
|
|
36
45
|
this._lambdaContext = options.lambdaContext;
|
|
37
46
|
this._lambdaEvent = options.lambdaEvent;
|
|
@@ -42,6 +51,18 @@ class LambdaRequest extends Readable {
|
|
|
42
51
|
remoteAddress: options.remoteAddress,
|
|
43
52
|
};
|
|
44
53
|
this.connection = this.socket;
|
|
54
|
+
// Schedule body push for next tick to ensure stream is ready
|
|
55
|
+
// This is needed for body parsers that consume the stream
|
|
56
|
+
if (this.bodyBuffer && this.bodyBuffer.length > 0) {
|
|
57
|
+
process.nextTick(() => {
|
|
58
|
+
if (!this.bodyPushed) {
|
|
59
|
+
this.push(this.bodyBuffer);
|
|
60
|
+
this.push(null);
|
|
61
|
+
this.bodyPushed = true;
|
|
62
|
+
this.complete = true;
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
}
|
|
45
66
|
}
|
|
46
67
|
//
|
|
47
68
|
// Readable stream implementation
|
|
@@ -143,6 +164,11 @@ function createLambdaRequest(event, context) {
|
|
|
143
164
|
body = event.isBase64Encoded
|
|
144
165
|
? Buffer.from(event.body, "base64")
|
|
145
166
|
: Buffer.from(event.body, "utf8");
|
|
167
|
+
// Add content-length header if not present (required for body parsers)
|
|
168
|
+
const hasContentLength = Object.keys(headers).some((k) => k.toLowerCase() === "content-length");
|
|
169
|
+
if (!hasContentLength) {
|
|
170
|
+
headers["content-length"] = String(body.length);
|
|
171
|
+
}
|
|
146
172
|
}
|
|
147
173
|
return new LambdaRequest({
|
|
148
174
|
body,
|
|
@@ -160,6 +186,9 @@ function createLambdaRequest(event, context) {
|
|
|
160
186
|
//
|
|
161
187
|
// Constants
|
|
162
188
|
//
|
|
189
|
+
// Symbol to identify Lambda mock responses. Uses Symbol.for() to ensure
|
|
190
|
+
// the same symbol is used across bundles/realms. Survives prototype manipulation.
|
|
191
|
+
const JAYPIE_LAMBDA_MOCK = Symbol.for("@jaypie/express/LambdaMock");
|
|
163
192
|
// Get Node's internal kOutHeaders symbol from ServerResponse prototype.
|
|
164
193
|
// This is needed for compatibility with Datadog dd-trace instrumentation,
|
|
165
194
|
// which patches HTTP methods and expects this internal state to exist.
|
|
@@ -193,21 +222,87 @@ class LambdaResponseBuffered extends Writable {
|
|
|
193
222
|
// Internal state exposed for direct manipulation by safe response methods
|
|
194
223
|
// that need to bypass dd-trace interception of stream methods
|
|
195
224
|
this._chunks = [];
|
|
225
|
+
this._ended = false; // Track ended state since writableEnded is lost after prototype change
|
|
196
226
|
this._headers = new Map();
|
|
197
227
|
this._headersSent = false;
|
|
198
228
|
this._resolve = null;
|
|
229
|
+
// Mark as Lambda mock response for identification in expressHandler
|
|
230
|
+
this[JAYPIE_LAMBDA_MOCK] = true;
|
|
199
231
|
// Initialize Node's internal kOutHeaders for dd-trace compatibility.
|
|
200
232
|
// dd-trace patches HTTP methods and expects this internal state.
|
|
201
233
|
if (kOutHeaders$1) {
|
|
202
234
|
this[kOutHeaders$1] = Object.create(null);
|
|
203
235
|
}
|
|
236
|
+
// CRITICAL: Define key methods as instance properties to survive Express's
|
|
237
|
+
// setPrototypeOf(res, app.response) in middleware/init.js which would
|
|
238
|
+
// otherwise replace our prototype with ServerResponse.prototype.
|
|
239
|
+
// Instance properties take precedence over prototype properties.
|
|
240
|
+
this.getHeader = this.getHeader.bind(this);
|
|
241
|
+
this.setHeader = this.setHeader.bind(this);
|
|
242
|
+
this.removeHeader = this.removeHeader.bind(this);
|
|
243
|
+
this.hasHeader = this.hasHeader.bind(this);
|
|
244
|
+
this.getHeaders = this.getHeaders.bind(this);
|
|
245
|
+
this.getHeaderNames = this.getHeaderNames.bind(this);
|
|
246
|
+
this.writeHead = this.writeHead.bind(this);
|
|
247
|
+
this.get = this.get.bind(this);
|
|
248
|
+
this.set = this.set.bind(this);
|
|
249
|
+
this.status = this.status.bind(this);
|
|
250
|
+
this.json = this.json.bind(this);
|
|
251
|
+
this.send = this.send.bind(this);
|
|
252
|
+
this.vary = this.vary.bind(this);
|
|
253
|
+
this.end = this.end.bind(this);
|
|
254
|
+
this.write = this.write.bind(this);
|
|
255
|
+
// Also bind internal Writable methods that are called via prototype chain
|
|
256
|
+
this._write = this._write.bind(this);
|
|
257
|
+
this._final = this._final.bind(this);
|
|
258
|
+
// Bind result-building methods
|
|
259
|
+
this.getResult = this.getResult.bind(this);
|
|
260
|
+
this.buildResult = this.buildResult.bind(this);
|
|
261
|
+
this.isBinaryContentType = this.isBinaryContentType.bind(this);
|
|
262
|
+
}
|
|
263
|
+
//
|
|
264
|
+
// Internal bypass methods - completely avoid prototype chain lookup
|
|
265
|
+
// These directly access _headers Map, safe from dd-trace interception
|
|
266
|
+
//
|
|
267
|
+
_internalGetHeader(name) {
|
|
268
|
+
const value = this._headers.get(name.toLowerCase());
|
|
269
|
+
return value ? String(value) : undefined;
|
|
270
|
+
}
|
|
271
|
+
_internalSetHeader(name, value) {
|
|
272
|
+
if (!this._headersSent) {
|
|
273
|
+
const lowerName = name.toLowerCase();
|
|
274
|
+
this._headers.set(lowerName, value);
|
|
275
|
+
// Also sync kOutHeaders for any code that expects it
|
|
276
|
+
if (kOutHeaders$1) {
|
|
277
|
+
const outHeaders = this[kOutHeaders$1];
|
|
278
|
+
if (outHeaders) {
|
|
279
|
+
outHeaders[lowerName] = [name, value];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
_internalHasHeader(name) {
|
|
285
|
+
return this._headers.has(name.toLowerCase());
|
|
286
|
+
}
|
|
287
|
+
_internalRemoveHeader(name) {
|
|
288
|
+
if (!this._headersSent) {
|
|
289
|
+
const lowerName = name.toLowerCase();
|
|
290
|
+
this._headers.delete(lowerName);
|
|
291
|
+
if (kOutHeaders$1) {
|
|
292
|
+
const outHeaders = this[kOutHeaders$1];
|
|
293
|
+
if (outHeaders) {
|
|
294
|
+
delete outHeaders[lowerName];
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
204
298
|
}
|
|
205
299
|
//
|
|
206
300
|
// Promise-based API for getting final result
|
|
207
301
|
//
|
|
208
302
|
getResult() {
|
|
209
303
|
return new Promise((resolve) => {
|
|
210
|
-
|
|
304
|
+
// Use _ended instead of writableEnded since Express's setPrototypeOf breaks the getter
|
|
305
|
+
if (this._ended) {
|
|
211
306
|
resolve(this.buildResult());
|
|
212
307
|
}
|
|
213
308
|
else {
|
|
@@ -265,36 +360,40 @@ class LambdaResponseBuffered extends Writable {
|
|
|
265
360
|
/**
|
|
266
361
|
* Proxy for direct header access (e.g., res.headers['content-type']).
|
|
267
362
|
* Required for compatibility with middleware like helmet that access headers directly.
|
|
363
|
+
* Uses direct _headers access to bypass dd-trace interception.
|
|
268
364
|
*/
|
|
269
365
|
get headers() {
|
|
270
366
|
return new Proxy({}, {
|
|
271
367
|
deleteProperty: (_target, prop) => {
|
|
272
|
-
this.
|
|
368
|
+
this._headers.delete(String(prop).toLowerCase());
|
|
273
369
|
return true;
|
|
274
370
|
},
|
|
275
371
|
get: (_target, prop) => {
|
|
276
372
|
if (typeof prop === "symbol")
|
|
277
373
|
return undefined;
|
|
278
|
-
return this.
|
|
374
|
+
return this._headers.get(String(prop).toLowerCase());
|
|
279
375
|
},
|
|
280
376
|
getOwnPropertyDescriptor: (_target, prop) => {
|
|
281
|
-
|
|
377
|
+
const lowerProp = String(prop).toLowerCase();
|
|
378
|
+
if (this._headers.has(lowerProp)) {
|
|
282
379
|
return {
|
|
283
380
|
configurable: true,
|
|
284
381
|
enumerable: true,
|
|
285
|
-
value: this.
|
|
382
|
+
value: this._headers.get(lowerProp),
|
|
286
383
|
};
|
|
287
384
|
}
|
|
288
385
|
return undefined;
|
|
289
386
|
},
|
|
290
387
|
has: (_target, prop) => {
|
|
291
|
-
return this.
|
|
388
|
+
return this._headers.has(String(prop).toLowerCase());
|
|
292
389
|
},
|
|
293
390
|
ownKeys: () => {
|
|
294
|
-
return this.
|
|
391
|
+
return Array.from(this._headers.keys());
|
|
295
392
|
},
|
|
296
393
|
set: (_target, prop, value) => {
|
|
297
|
-
this.
|
|
394
|
+
if (!this._headersSent) {
|
|
395
|
+
this._headers.set(String(prop).toLowerCase(), value);
|
|
396
|
+
}
|
|
298
397
|
return true;
|
|
299
398
|
},
|
|
300
399
|
});
|
|
@@ -311,9 +410,10 @@ class LambdaResponseBuffered extends Writable {
|
|
|
311
410
|
headersToSet = statusMessageOrHeaders;
|
|
312
411
|
}
|
|
313
412
|
if (headersToSet) {
|
|
413
|
+
// Use direct _headers access to bypass dd-trace interception
|
|
314
414
|
for (const [key, value] of Object.entries(headersToSet)) {
|
|
315
415
|
if (value !== undefined) {
|
|
316
|
-
this.
|
|
416
|
+
this._headers.set(key.toLowerCase(), String(value));
|
|
317
417
|
}
|
|
318
418
|
}
|
|
319
419
|
}
|
|
@@ -350,7 +450,8 @@ class LambdaResponseBuffered extends Writable {
|
|
|
350
450
|
return this;
|
|
351
451
|
}
|
|
352
452
|
json(data) {
|
|
353
|
-
|
|
453
|
+
// Use direct _headers access to bypass dd-trace interception
|
|
454
|
+
this._headers.set("content-type", "application/json");
|
|
354
455
|
this.end(JSON.stringify(data));
|
|
355
456
|
return this;
|
|
356
457
|
}
|
|
@@ -364,11 +465,12 @@ class LambdaResponseBuffered extends Writable {
|
|
|
364
465
|
/**
|
|
365
466
|
* Add a field to the Vary response header.
|
|
366
467
|
* Used by CORS middleware to indicate response varies by Origin.
|
|
468
|
+
* Uses direct _headers access to bypass dd-trace interception.
|
|
367
469
|
*/
|
|
368
470
|
vary(field) {
|
|
369
|
-
const existing = this.
|
|
471
|
+
const existing = this._headers.get("vary");
|
|
370
472
|
if (!existing) {
|
|
371
|
-
this.
|
|
473
|
+
this._headers.set("vary", field);
|
|
372
474
|
}
|
|
373
475
|
else {
|
|
374
476
|
// Append to existing Vary header if field not already present
|
|
@@ -376,7 +478,7 @@ class LambdaResponseBuffered extends Writable {
|
|
|
376
478
|
.split(",")
|
|
377
479
|
.map((f) => f.trim().toLowerCase());
|
|
378
480
|
if (!fields.includes(field.toLowerCase())) {
|
|
379
|
-
this.
|
|
481
|
+
this._headers.set("vary", `${existing}, ${field}`);
|
|
380
482
|
}
|
|
381
483
|
}
|
|
382
484
|
return this;
|
|
@@ -394,6 +496,7 @@ class LambdaResponseBuffered extends Writable {
|
|
|
394
496
|
callback();
|
|
395
497
|
}
|
|
396
498
|
_final(callback) {
|
|
499
|
+
this._ended = true;
|
|
397
500
|
if (this._resolve) {
|
|
398
501
|
this._resolve(this.buildResult());
|
|
399
502
|
}
|
|
@@ -404,7 +507,8 @@ class LambdaResponseBuffered extends Writable {
|
|
|
404
507
|
//
|
|
405
508
|
buildResult() {
|
|
406
509
|
const body = Buffer.concat(this._chunks);
|
|
407
|
-
|
|
510
|
+
// Use direct _headers access to bypass dd-trace interception
|
|
511
|
+
const contentType = this._headers.get("content-type") || "";
|
|
408
512
|
// Determine if response should be base64 encoded
|
|
409
513
|
const isBase64Encoded = this.isBinaryContentType(contentType);
|
|
410
514
|
// Build headers object
|
|
@@ -466,6 +570,8 @@ class LambdaResponseStreaming extends Writable {
|
|
|
466
570
|
this.socket = {
|
|
467
571
|
remoteAddress: "127.0.0.1",
|
|
468
572
|
};
|
|
573
|
+
// Internal state exposed for direct manipulation by safe response methods
|
|
574
|
+
// that need to bypass dd-trace interception
|
|
469
575
|
this._headers = new Map();
|
|
470
576
|
this._headersSent = false;
|
|
471
577
|
this._pendingWrites = [];
|
|
@@ -476,6 +582,65 @@ class LambdaResponseStreaming extends Writable {
|
|
|
476
582
|
if (kOutHeaders) {
|
|
477
583
|
this[kOutHeaders] = Object.create(null);
|
|
478
584
|
}
|
|
585
|
+
// CRITICAL: Define key methods as instance properties to survive Express's
|
|
586
|
+
// setPrototypeOf(res, app.response) in middleware/init.js which would
|
|
587
|
+
// otherwise replace our prototype with ServerResponse.prototype.
|
|
588
|
+
// Instance properties take precedence over prototype properties.
|
|
589
|
+
this.getHeader = this.getHeader.bind(this);
|
|
590
|
+
this.setHeader = this.setHeader.bind(this);
|
|
591
|
+
this.removeHeader = this.removeHeader.bind(this);
|
|
592
|
+
this.hasHeader = this.hasHeader.bind(this);
|
|
593
|
+
this.getHeaders = this.getHeaders.bind(this);
|
|
594
|
+
this.getHeaderNames = this.getHeaderNames.bind(this);
|
|
595
|
+
this.writeHead = this.writeHead.bind(this);
|
|
596
|
+
this.flushHeaders = this.flushHeaders.bind(this);
|
|
597
|
+
this.get = this.get.bind(this);
|
|
598
|
+
this.set = this.set.bind(this);
|
|
599
|
+
this.status = this.status.bind(this);
|
|
600
|
+
this.json = this.json.bind(this);
|
|
601
|
+
this.send = this.send.bind(this);
|
|
602
|
+
this.vary = this.vary.bind(this);
|
|
603
|
+
this.end = this.end.bind(this);
|
|
604
|
+
this.write = this.write.bind(this);
|
|
605
|
+
// Also bind internal Writable methods that are called via prototype chain
|
|
606
|
+
this._write = this._write.bind(this);
|
|
607
|
+
this._final = this._final.bind(this);
|
|
608
|
+
}
|
|
609
|
+
//
|
|
610
|
+
// Internal bypass methods - completely avoid prototype chain lookup
|
|
611
|
+
// These directly access _headers Map, safe from dd-trace interception
|
|
612
|
+
//
|
|
613
|
+
_internalGetHeader(name) {
|
|
614
|
+
const value = this._headers.get(name.toLowerCase());
|
|
615
|
+
return value ? String(value) : undefined;
|
|
616
|
+
}
|
|
617
|
+
_internalSetHeader(name, value) {
|
|
618
|
+
if (!this._headersSent) {
|
|
619
|
+
const lowerName = name.toLowerCase();
|
|
620
|
+
this._headers.set(lowerName, value);
|
|
621
|
+
// Also sync kOutHeaders for any code that expects it
|
|
622
|
+
if (kOutHeaders) {
|
|
623
|
+
const outHeaders = this[kOutHeaders];
|
|
624
|
+
if (outHeaders) {
|
|
625
|
+
outHeaders[lowerName] = [name, value];
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
_internalHasHeader(name) {
|
|
631
|
+
return this._headers.has(name.toLowerCase());
|
|
632
|
+
}
|
|
633
|
+
_internalRemoveHeader(name) {
|
|
634
|
+
if (!this._headersSent) {
|
|
635
|
+
const lowerName = name.toLowerCase();
|
|
636
|
+
this._headers.delete(lowerName);
|
|
637
|
+
if (kOutHeaders) {
|
|
638
|
+
const outHeaders = this[kOutHeaders];
|
|
639
|
+
if (outHeaders) {
|
|
640
|
+
delete outHeaders[lowerName];
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
}
|
|
479
644
|
}
|
|
480
645
|
//
|
|
481
646
|
// Header management
|
|
@@ -530,36 +695,42 @@ class LambdaResponseStreaming extends Writable {
|
|
|
530
695
|
/**
|
|
531
696
|
* Proxy for direct header access (e.g., res.headers['content-type']).
|
|
532
697
|
* Required for compatibility with middleware like helmet that access headers directly.
|
|
698
|
+
* Uses direct _headers access to bypass dd-trace interception.
|
|
533
699
|
*/
|
|
534
700
|
get headers() {
|
|
535
701
|
return new Proxy({}, {
|
|
536
702
|
deleteProperty: (_target, prop) => {
|
|
537
|
-
this.
|
|
703
|
+
if (!this._headersSent) {
|
|
704
|
+
this._headers.delete(String(prop).toLowerCase());
|
|
705
|
+
}
|
|
538
706
|
return true;
|
|
539
707
|
},
|
|
540
708
|
get: (_target, prop) => {
|
|
541
709
|
if (typeof prop === "symbol")
|
|
542
710
|
return undefined;
|
|
543
|
-
return this.
|
|
711
|
+
return this._headers.get(String(prop).toLowerCase());
|
|
544
712
|
},
|
|
545
713
|
getOwnPropertyDescriptor: (_target, prop) => {
|
|
546
|
-
|
|
714
|
+
const lowerProp = String(prop).toLowerCase();
|
|
715
|
+
if (this._headers.has(lowerProp)) {
|
|
547
716
|
return {
|
|
548
717
|
configurable: true,
|
|
549
718
|
enumerable: true,
|
|
550
|
-
value: this.
|
|
719
|
+
value: this._headers.get(lowerProp),
|
|
551
720
|
};
|
|
552
721
|
}
|
|
553
722
|
return undefined;
|
|
554
723
|
},
|
|
555
724
|
has: (_target, prop) => {
|
|
556
|
-
return this.
|
|
725
|
+
return this._headers.has(String(prop).toLowerCase());
|
|
557
726
|
},
|
|
558
727
|
ownKeys: () => {
|
|
559
|
-
return this.
|
|
728
|
+
return Array.from(this._headers.keys());
|
|
560
729
|
},
|
|
561
730
|
set: (_target, prop, value) => {
|
|
562
|
-
this.
|
|
731
|
+
if (!this._headersSent) {
|
|
732
|
+
this._headers.set(String(prop).toLowerCase(), value);
|
|
733
|
+
}
|
|
563
734
|
return true;
|
|
564
735
|
},
|
|
565
736
|
});
|
|
@@ -579,9 +750,10 @@ class LambdaResponseStreaming extends Writable {
|
|
|
579
750
|
headersToSet = statusMessageOrHeaders;
|
|
580
751
|
}
|
|
581
752
|
if (headersToSet) {
|
|
753
|
+
// Use direct _headers access to bypass dd-trace interception
|
|
582
754
|
for (const [key, value] of Object.entries(headersToSet)) {
|
|
583
755
|
if (value !== undefined) {
|
|
584
|
-
this.
|
|
756
|
+
this._headers.set(key.toLowerCase(), String(value));
|
|
585
757
|
}
|
|
586
758
|
}
|
|
587
759
|
}
|
|
@@ -639,7 +811,8 @@ class LambdaResponseStreaming extends Writable {
|
|
|
639
811
|
return this;
|
|
640
812
|
}
|
|
641
813
|
json(data) {
|
|
642
|
-
|
|
814
|
+
// Use direct _headers access to bypass dd-trace interception
|
|
815
|
+
this._headers.set("content-type", "application/json");
|
|
643
816
|
this.end(JSON.stringify(data));
|
|
644
817
|
return this;
|
|
645
818
|
}
|
|
@@ -653,11 +826,12 @@ class LambdaResponseStreaming extends Writable {
|
|
|
653
826
|
/**
|
|
654
827
|
* Add a field to the Vary response header.
|
|
655
828
|
* Used by CORS middleware to indicate response varies by Origin.
|
|
829
|
+
* Uses direct _headers access to bypass dd-trace interception.
|
|
656
830
|
*/
|
|
657
831
|
vary(field) {
|
|
658
|
-
const existing = this.
|
|
832
|
+
const existing = this._headers.get("vary");
|
|
659
833
|
if (!existing) {
|
|
660
|
-
this.
|
|
834
|
+
this._headers.set("vary", field);
|
|
661
835
|
}
|
|
662
836
|
else {
|
|
663
837
|
// Append to existing Vary header if field not already present
|
|
@@ -665,7 +839,7 @@ class LambdaResponseStreaming extends Writable {
|
|
|
665
839
|
.split(",")
|
|
666
840
|
.map((f) => f.trim().toLowerCase());
|
|
667
841
|
if (!fields.includes(field.toLowerCase())) {
|
|
668
|
-
this.
|
|
842
|
+
this._headers.set("vary", `${existing}, ${field}`);
|
|
669
843
|
}
|
|
670
844
|
}
|
|
671
845
|
return this;
|
|
@@ -763,6 +937,7 @@ function runExpressApp(app, req, res) {
|
|
|
763
937
|
*/
|
|
764
938
|
function createLambdaHandler(app, _options) {
|
|
765
939
|
return async (event, context) => {
|
|
940
|
+
let result;
|
|
766
941
|
try {
|
|
767
942
|
// Set current invoke for getCurrentInvokeUuid
|
|
768
943
|
setCurrentInvoke(event, context);
|
|
@@ -772,8 +947,38 @@ function createLambdaHandler(app, _options) {
|
|
|
772
947
|
const res = new LambdaResponseBuffered();
|
|
773
948
|
// Run Express app
|
|
774
949
|
await runExpressApp(app, req, res);
|
|
775
|
-
//
|
|
776
|
-
|
|
950
|
+
// Get Lambda response - await explicitly to ensure we have the result
|
|
951
|
+
result = await res.getResult();
|
|
952
|
+
// Debug: Log the response before returning
|
|
953
|
+
console.log("[createLambdaHandler] Returning response:", JSON.stringify({
|
|
954
|
+
statusCode: result.statusCode,
|
|
955
|
+
headers: result.headers,
|
|
956
|
+
bodyLength: result.body?.length,
|
|
957
|
+
isBase64Encoded: result.isBase64Encoded,
|
|
958
|
+
}));
|
|
959
|
+
return result;
|
|
960
|
+
}
|
|
961
|
+
catch (error) {
|
|
962
|
+
// Log any unhandled errors
|
|
963
|
+
console.error("[createLambdaHandler] Unhandled error:", error);
|
|
964
|
+
if (error instanceof Error) {
|
|
965
|
+
console.error("[createLambdaHandler] Stack:", error.stack);
|
|
966
|
+
}
|
|
967
|
+
// Return a proper error response instead of throwing
|
|
968
|
+
return {
|
|
969
|
+
statusCode: 500,
|
|
970
|
+
headers: { "content-type": "application/json" },
|
|
971
|
+
body: JSON.stringify({
|
|
972
|
+
errors: [
|
|
973
|
+
{
|
|
974
|
+
status: 500,
|
|
975
|
+
title: "Internal Server Error",
|
|
976
|
+
detail: error instanceof Error ? error.message : "Unknown error occurred",
|
|
977
|
+
},
|
|
978
|
+
],
|
|
979
|
+
}),
|
|
980
|
+
isBase64Encoded: false,
|
|
981
|
+
};
|
|
777
982
|
}
|
|
778
983
|
finally {
|
|
779
984
|
// Clear current invoke context
|
|
@@ -911,7 +1116,7 @@ const corsHelper = (config = {}) => {
|
|
|
911
1116
|
};
|
|
912
1117
|
return expressCors(options);
|
|
913
1118
|
};
|
|
914
|
-
var
|
|
1119
|
+
var cors_helper = (config) => {
|
|
915
1120
|
const cors = corsHelper(config);
|
|
916
1121
|
return (req, res, next) => {
|
|
917
1122
|
cors(req, res, (error) => {
|
|
@@ -926,154 +1131,10 @@ var cors = (config) => {
|
|
|
926
1131
|
};
|
|
927
1132
|
};
|
|
928
1133
|
|
|
929
|
-
//
|
|
930
|
-
//
|
|
931
|
-
// Constants
|
|
932
|
-
//
|
|
933
|
-
const DEFAULT_PORT = 8080;
|
|
934
|
-
//
|
|
935
|
-
//
|
|
936
|
-
// Main
|
|
937
|
-
//
|
|
938
|
-
/**
|
|
939
|
-
* Creates and starts an Express server with standard Jaypie middleware.
|
|
940
|
-
*
|
|
941
|
-
* Features:
|
|
942
|
-
* - CORS handling (configurable)
|
|
943
|
-
* - JSON body parsing
|
|
944
|
-
* - Listens on PORT env var (default 8080)
|
|
945
|
-
*
|
|
946
|
-
* Usage:
|
|
947
|
-
* ```ts
|
|
948
|
-
* import express from "express";
|
|
949
|
-
* import { createServer, expressHandler } from "@jaypie/express";
|
|
950
|
-
*
|
|
951
|
-
* const app = express();
|
|
952
|
-
*
|
|
953
|
-
* app.get("/", expressHandler(async (req, res) => {
|
|
954
|
-
* return { message: "Hello World" };
|
|
955
|
-
* }));
|
|
956
|
-
*
|
|
957
|
-
* const { server, port } = await createServer(app);
|
|
958
|
-
* console.log(`Server running on port ${port}`);
|
|
959
|
-
* ```
|
|
960
|
-
*
|
|
961
|
-
* @param app - Express application instance
|
|
962
|
-
* @param options - Server configuration options
|
|
963
|
-
* @returns Promise resolving to server instance and port
|
|
964
|
-
*/
|
|
965
|
-
async function createServer(app, options = {}) {
|
|
966
|
-
const { cors: corsConfig, jsonLimit = "1mb", middleware = [], port: portOption, } = options;
|
|
967
|
-
// Determine port
|
|
968
|
-
const port = typeof portOption === "string"
|
|
969
|
-
? parseInt(portOption, 10)
|
|
970
|
-
: (portOption ?? parseInt(process.env.PORT || String(DEFAULT_PORT), 10));
|
|
971
|
-
// Apply CORS middleware (unless explicitly disabled)
|
|
972
|
-
if (corsConfig !== false) {
|
|
973
|
-
app.use(cors(corsConfig));
|
|
974
|
-
}
|
|
975
|
-
// Apply JSON body parser
|
|
976
|
-
// Note: We use dynamic import to avoid requiring express as a direct dependency
|
|
977
|
-
const express = await import('express');
|
|
978
|
-
app.use(express.json({ limit: jsonLimit }));
|
|
979
|
-
// Apply additional middleware
|
|
980
|
-
for (const mw of middleware) {
|
|
981
|
-
app.use(mw);
|
|
982
|
-
}
|
|
983
|
-
// Start server
|
|
984
|
-
return new Promise((resolve, reject) => {
|
|
985
|
-
try {
|
|
986
|
-
const server = app.listen(port, () => {
|
|
987
|
-
// Get the actual port (important when port 0 is passed to get an ephemeral port)
|
|
988
|
-
const address = server.address();
|
|
989
|
-
const actualPort = address?.port ?? port;
|
|
990
|
-
log.info(`Server listening on port ${actualPort}`);
|
|
991
|
-
resolve({ port: actualPort, server });
|
|
992
|
-
});
|
|
993
|
-
server.on("error", (error) => {
|
|
994
|
-
log.error("Server error", { error });
|
|
995
|
-
reject(error);
|
|
996
|
-
});
|
|
997
|
-
}
|
|
998
|
-
catch (error) {
|
|
999
|
-
reject(error);
|
|
1000
|
-
}
|
|
1001
|
-
});
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
|
-
//
|
|
1005
|
-
//
|
|
1006
|
-
// Constants
|
|
1007
|
-
//
|
|
1008
|
-
const HEADER_AMZN_REQUEST_ID$1 = "x-amzn-request-id";
|
|
1009
|
-
const ENV_AMZN_TRACE_ID = "_X_AMZN_TRACE_ID";
|
|
1010
1134
|
//
|
|
1011
1135
|
//
|
|
1012
1136
|
// Helper Functions
|
|
1013
1137
|
//
|
|
1014
|
-
/**
|
|
1015
|
-
* Extract request ID from X-Ray trace ID environment variable
|
|
1016
|
-
* Format: Root=1-5e6b4a90-example;Parent=example;Sampled=1
|
|
1017
|
-
* We extract the trace ID from the Root segment
|
|
1018
|
-
*/
|
|
1019
|
-
function parseTraceId(traceId) {
|
|
1020
|
-
if (!traceId)
|
|
1021
|
-
return undefined;
|
|
1022
|
-
// Extract the Root segment (format: Root=1-{timestamp}-{uuid})
|
|
1023
|
-
const rootMatch = traceId.match(/Root=([^;]+)/);
|
|
1024
|
-
if (rootMatch && rootMatch[1]) {
|
|
1025
|
-
return rootMatch[1];
|
|
1026
|
-
}
|
|
1027
|
-
return undefined;
|
|
1028
|
-
}
|
|
1029
|
-
//
|
|
1030
|
-
//
|
|
1031
|
-
// Main
|
|
1032
|
-
//
|
|
1033
|
-
/**
|
|
1034
|
-
* Get the current invoke UUID from Lambda Web Adapter context.
|
|
1035
|
-
* This function extracts the request ID from either:
|
|
1036
|
-
* 1. The x-amzn-request-id header (set by Lambda Web Adapter)
|
|
1037
|
-
* 2. The _X_AMZN_TRACE_ID environment variable (set by Lambda runtime)
|
|
1038
|
-
*
|
|
1039
|
-
* @param req - Optional Express request object to extract headers from
|
|
1040
|
-
* @returns The AWS request ID or undefined if not in Lambda context
|
|
1041
|
-
*/
|
|
1042
|
-
function getWebAdapterUuid(req) {
|
|
1043
|
-
// First, try to get from request headers
|
|
1044
|
-
if (req && req.headers) {
|
|
1045
|
-
const headerValue = req.headers[HEADER_AMZN_REQUEST_ID$1];
|
|
1046
|
-
if (headerValue) {
|
|
1047
|
-
return Array.isArray(headerValue) ? headerValue[0] : headerValue;
|
|
1048
|
-
}
|
|
1049
|
-
}
|
|
1050
|
-
// Fall back to environment variable (X-Ray trace ID)
|
|
1051
|
-
const traceId = process.env[ENV_AMZN_TRACE_ID];
|
|
1052
|
-
if (traceId) {
|
|
1053
|
-
return parseTraceId(traceId);
|
|
1054
|
-
}
|
|
1055
|
-
return undefined;
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
//
|
|
1059
|
-
//
|
|
1060
|
-
// Constants
|
|
1061
|
-
//
|
|
1062
|
-
const HEADER_AMZN_REQUEST_ID = "x-amzn-request-id";
|
|
1063
|
-
//
|
|
1064
|
-
//
|
|
1065
|
-
// Helper Functions
|
|
1066
|
-
//
|
|
1067
|
-
/**
|
|
1068
|
-
* Detect if we're running in Lambda Web Adapter mode.
|
|
1069
|
-
* Web Adapter sets the x-amzn-request-id header on requests.
|
|
1070
|
-
*/
|
|
1071
|
-
function isWebAdapterMode(req) {
|
|
1072
|
-
if (req && req.headers && req.headers[HEADER_AMZN_REQUEST_ID]) {
|
|
1073
|
-
return true;
|
|
1074
|
-
}
|
|
1075
|
-
return false;
|
|
1076
|
-
}
|
|
1077
1138
|
/**
|
|
1078
1139
|
* Get UUID from Jaypie Lambda adapter context.
|
|
1079
1140
|
* This is set by createLambdaHandler/createLambdaStreamHandler.
|
|
@@ -1090,8 +1151,12 @@ function getJaypieAdapterUuid() {
|
|
|
1090
1151
|
* The Jaypie adapter attaches _lambdaContext to the request.
|
|
1091
1152
|
*/
|
|
1092
1153
|
function getRequestContextUuid(req) {
|
|
1093
|
-
if (req && req._lambdaContext
|
|
1094
|
-
|
|
1154
|
+
if (req && req._lambdaContext) {
|
|
1155
|
+
const lambdaContext = req
|
|
1156
|
+
._lambdaContext;
|
|
1157
|
+
if (lambdaContext.awsRequestId) {
|
|
1158
|
+
return lambdaContext.awsRequestId;
|
|
1159
|
+
}
|
|
1095
1160
|
}
|
|
1096
1161
|
return undefined;
|
|
1097
1162
|
}
|
|
@@ -1101,29 +1166,20 @@ function getRequestContextUuid(req) {
|
|
|
1101
1166
|
//
|
|
1102
1167
|
/**
|
|
1103
1168
|
* Get the current invoke UUID from Lambda context.
|
|
1104
|
-
* Works with Jaypie Lambda adapter
|
|
1169
|
+
* Works with Jaypie Lambda adapter (createLambdaHandler/createLambdaStreamHandler).
|
|
1105
1170
|
*
|
|
1106
1171
|
* @param req - Optional Express request object. Used to extract context
|
|
1107
|
-
* from
|
|
1172
|
+
* from Jaypie adapter's _lambdaContext.
|
|
1108
1173
|
* @returns The AWS request ID or undefined if not in Lambda context
|
|
1109
1174
|
*/
|
|
1110
1175
|
function getCurrentInvokeUuid(req) {
|
|
1111
|
-
// Priority 1:
|
|
1112
|
-
if (isWebAdapterMode(req)) {
|
|
1113
|
-
return getWebAdapterUuid(req);
|
|
1114
|
-
}
|
|
1115
|
-
// Priority 2: Request has Lambda context attached (Jaypie adapter)
|
|
1176
|
+
// Priority 1: Request has Lambda context attached (Jaypie adapter)
|
|
1116
1177
|
const requestContextUuid = getRequestContextUuid(req);
|
|
1117
1178
|
if (requestContextUuid) {
|
|
1118
1179
|
return requestContextUuid;
|
|
1119
1180
|
}
|
|
1120
|
-
// Priority
|
|
1121
|
-
|
|
1122
|
-
if (jaypieAdapterUuid) {
|
|
1123
|
-
return jaypieAdapterUuid;
|
|
1124
|
-
}
|
|
1125
|
-
// Fallback: Web Adapter env var
|
|
1126
|
-
return getWebAdapterUuid();
|
|
1181
|
+
// Priority 2: Global context from Jaypie adapter
|
|
1182
|
+
return getJaypieAdapterUuid();
|
|
1127
1183
|
}
|
|
1128
1184
|
|
|
1129
1185
|
//
|
|
@@ -1137,7 +1193,11 @@ function getCurrentInvokeUuid(req) {
|
|
|
1137
1193
|
*/
|
|
1138
1194
|
function safeGetHeader(res, name) {
|
|
1139
1195
|
try {
|
|
1140
|
-
// Try
|
|
1196
|
+
// Try internal method first (completely bypasses dd-trace)
|
|
1197
|
+
if (typeof res._internalGetHeader === "function") {
|
|
1198
|
+
return res._internalGetHeader(name);
|
|
1199
|
+
}
|
|
1200
|
+
// Fall back to _headers Map access (Lambda adapter, avoids dd-trace)
|
|
1141
1201
|
if (res._headers instanceof Map) {
|
|
1142
1202
|
const value = res._headers.get(name.toLowerCase());
|
|
1143
1203
|
return value ? String(value) : undefined;
|
|
@@ -1165,7 +1225,12 @@ function safeGetHeader(res, name) {
|
|
|
1165
1225
|
*/
|
|
1166
1226
|
function safeSetHeader(res, name, value) {
|
|
1167
1227
|
try {
|
|
1168
|
-
// Try
|
|
1228
|
+
// Try internal method first (completely bypasses dd-trace)
|
|
1229
|
+
if (typeof res._internalSetHeader === "function") {
|
|
1230
|
+
res._internalSetHeader(name, value);
|
|
1231
|
+
return;
|
|
1232
|
+
}
|
|
1233
|
+
// Fall back to _headers Map access (Lambda adapter, avoids dd-trace)
|
|
1169
1234
|
if (res._headers instanceof Map) {
|
|
1170
1235
|
res._headers.set(name.toLowerCase(), value);
|
|
1171
1236
|
return;
|
|
@@ -1296,12 +1361,10 @@ const logger$1 = log;
|
|
|
1296
1361
|
//
|
|
1297
1362
|
/**
|
|
1298
1363
|
* Check if response is a Lambda mock response with direct internal access.
|
|
1364
|
+
* Uses Symbol marker to survive prototype chain modifications from Express and dd-trace.
|
|
1299
1365
|
*/
|
|
1300
1366
|
function isLambdaMockResponse(res) {
|
|
1301
|
-
|
|
1302
|
-
return (mock._headers instanceof Map &&
|
|
1303
|
-
Array.isArray(mock._chunks) &&
|
|
1304
|
-
typeof mock.buildResult === "function");
|
|
1367
|
+
return res[JAYPIE_LAMBDA_MOCK] === true;
|
|
1305
1368
|
}
|
|
1306
1369
|
/**
|
|
1307
1370
|
* Safely send a JSON response, avoiding dd-trace interception.
|
|
@@ -1310,17 +1373,28 @@ function isLambdaMockResponse(res) {
|
|
|
1310
1373
|
*/
|
|
1311
1374
|
function safeSendJson(res, statusCode, data) {
|
|
1312
1375
|
if (isLambdaMockResponse(res)) {
|
|
1313
|
-
//
|
|
1314
|
-
res.
|
|
1376
|
+
// Use internal method to set header (completely bypasses dd-trace)
|
|
1377
|
+
if (typeof res._internalSetHeader === "function") {
|
|
1378
|
+
res._internalSetHeader("content-type", "application/json");
|
|
1379
|
+
}
|
|
1380
|
+
else {
|
|
1381
|
+
// Fall back to direct _headers manipulation
|
|
1382
|
+
res._headers.set("content-type", "application/json");
|
|
1383
|
+
}
|
|
1315
1384
|
res.statusCode = statusCode;
|
|
1316
1385
|
// Directly push to chunks array instead of using stream write/end
|
|
1317
1386
|
const chunk = Buffer.from(JSON.stringify(data));
|
|
1318
1387
|
res._chunks.push(chunk);
|
|
1319
1388
|
res._headersSent = true;
|
|
1389
|
+
// Mark as ended so getResult() resolves immediately
|
|
1390
|
+
res._ended = true;
|
|
1320
1391
|
// Signal completion if a promise is waiting
|
|
1321
1392
|
if (res._resolve) {
|
|
1322
1393
|
res._resolve(res.buildResult());
|
|
1323
1394
|
}
|
|
1395
|
+
// Emit "finish" event so runExpressApp's promise resolves
|
|
1396
|
+
console.log("[safeSendJson] Emitting finish event");
|
|
1397
|
+
res.emit("finish");
|
|
1324
1398
|
return;
|
|
1325
1399
|
}
|
|
1326
1400
|
// Fall back to standard Express methods for real responses
|
|
@@ -1340,10 +1414,15 @@ function safeSend(res, statusCode, body) {
|
|
|
1340
1414
|
res._chunks.push(chunk);
|
|
1341
1415
|
}
|
|
1342
1416
|
res._headersSent = true;
|
|
1417
|
+
// Mark as ended so getResult() resolves immediately
|
|
1418
|
+
res._ended = true;
|
|
1343
1419
|
// Signal completion if a promise is waiting
|
|
1344
1420
|
if (res._resolve) {
|
|
1345
1421
|
res._resolve(res.buildResult());
|
|
1346
1422
|
}
|
|
1423
|
+
// Emit "finish" event so runExpressApp's promise resolves
|
|
1424
|
+
console.log("[safeSend] Emitting finish event");
|
|
1425
|
+
res.emit("finish");
|
|
1347
1426
|
return;
|
|
1348
1427
|
}
|
|
1349
1428
|
// Fall back to standard Express methods for real responses
|
|
@@ -1610,7 +1689,18 @@ function expressHandler(handlerOrOptions, optionsOrHandler) {
|
|
|
1610
1689
|
}
|
|
1611
1690
|
}
|
|
1612
1691
|
catch (error) {
|
|
1613
|
-
|
|
1692
|
+
// Use console.error for raw stack trace to ensure it appears in CloudWatch
|
|
1693
|
+
// Handle both Error objects and plain thrown values
|
|
1694
|
+
const errorMessage = error instanceof Error
|
|
1695
|
+
? error.message
|
|
1696
|
+
: typeof error === "object" && error !== null
|
|
1697
|
+
? JSON.stringify(error)
|
|
1698
|
+
: String(error);
|
|
1699
|
+
const errorStack = error instanceof Error
|
|
1700
|
+
? error.stack
|
|
1701
|
+
: new Error("Stack trace").stack?.replace("Error: Stack trace", `Error: ${errorMessage}`);
|
|
1702
|
+
console.error("Express response error stack trace:", errorStack);
|
|
1703
|
+
log.fatal(`Express encountered an error while sending the response: ${errorMessage}`);
|
|
1614
1704
|
log.var({ responseError: error });
|
|
1615
1705
|
}
|
|
1616
1706
|
// Log response
|
|
@@ -1710,14 +1800,13 @@ const logger = log;
|
|
|
1710
1800
|
// Helper
|
|
1711
1801
|
//
|
|
1712
1802
|
/**
|
|
1713
|
-
*
|
|
1803
|
+
* Get error body from an error
|
|
1714
1804
|
*/
|
|
1715
|
-
function
|
|
1805
|
+
function getErrorBody(error) {
|
|
1716
1806
|
const isJaypieError = error.isProjectError;
|
|
1717
|
-
|
|
1807
|
+
return isJaypieError
|
|
1718
1808
|
? (error.body?.() ?? { error: error.message })
|
|
1719
1809
|
: new UnhandledError().body();
|
|
1720
|
-
return `event: error\ndata: ${JSON.stringify(body)}\n\n`;
|
|
1721
1810
|
}
|
|
1722
1811
|
function expressStreamHandler(handlerOrOptions, optionsOrHandler) {
|
|
1723
1812
|
/* eslint-enable no-redeclare */
|
|
@@ -1737,7 +1826,8 @@ function expressStreamHandler(handlerOrOptions, optionsOrHandler) {
|
|
|
1737
1826
|
//
|
|
1738
1827
|
// Validate
|
|
1739
1828
|
//
|
|
1740
|
-
|
|
1829
|
+
const format = options.format ?? "sse";
|
|
1830
|
+
let { chaos, contentType = getContentTypeForFormat(format), locals, name, secrets, setup = [], teardown = [], unavailable, validate, } = options;
|
|
1741
1831
|
if (typeof handler !== "function") {
|
|
1742
1832
|
throw new BadRequestError(`Argument "${handler}" doesn't match type "function"`);
|
|
1743
1833
|
}
|
|
@@ -1875,9 +1965,10 @@ function expressStreamHandler(handlerOrOptions, optionsOrHandler) {
|
|
|
1875
1965
|
log.fatal("Caught unhandled error in stream handler");
|
|
1876
1966
|
log.info.var({ unhandledError: error.message });
|
|
1877
1967
|
}
|
|
1878
|
-
// Write error
|
|
1968
|
+
// Write error in the appropriate format
|
|
1879
1969
|
try {
|
|
1880
|
-
|
|
1970
|
+
const errorBody = getErrorBody(error);
|
|
1971
|
+
res.write(formatStreamError(errorBody, format));
|
|
1881
1972
|
}
|
|
1882
1973
|
catch {
|
|
1883
1974
|
// Response may already be closed
|
|
@@ -1986,5 +2077,5 @@ const noContentRoute = routes.noContentRoute;
|
|
|
1986
2077
|
const notFoundRoute = routes.notFoundRoute;
|
|
1987
2078
|
const notImplementedRoute = routes.notImplementedRoute;
|
|
1988
2079
|
|
|
1989
|
-
export { EXPRESS, LambdaRequest, LambdaResponseBuffered, LambdaResponseStreaming, badRequestRoute, cors, createLambdaHandler, createLambdaStreamHandler,
|
|
2080
|
+
export { EXPRESS, LambdaRequest, LambdaResponseBuffered, LambdaResponseStreaming, badRequestRoute, cors_helper as cors, createLambdaHandler, createLambdaStreamHandler, echoRoute, expressHandler, httpHandler as expressHttpCodeHandler, expressStreamHandler, forbiddenRoute, getCurrentInvoke, getCurrentInvokeUuid, goneRoute, methodNotAllowedRoute, noContentRoute, notFoundRoute, notImplementedRoute };
|
|
1990
2081
|
//# sourceMappingURL=index.js.map
|