@jaypie/express 1.2.4-rc14 → 1.2.4-rc16
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 +1 -0
- package/dist/cjs/adapter/__tests__/debug-harness.d.ts +1 -0
- package/dist/cjs/index.cjs +84 -6
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/adapter/LambdaResponseBuffered.d.ts +1 -0
- package/dist/esm/adapter/__tests__/debug-harness.d.ts +1 -0
- package/dist/esm/index.js +84 -6
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,6 +12,7 @@ export declare class LambdaResponseBuffered extends Writable {
|
|
|
12
12
|
remoteAddress: string;
|
|
13
13
|
};
|
|
14
14
|
_chunks: Buffer[];
|
|
15
|
+
_ended: boolean;
|
|
15
16
|
_headers: Map<string, string | string[]>;
|
|
16
17
|
_headersSent: boolean;
|
|
17
18
|
_resolve: ((result: LambdaResponse) => void) | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/esm/index.js
CHANGED
|
@@ -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,
|
|
@@ -193,6 +219,7 @@ class LambdaResponseBuffered extends Writable {
|
|
|
193
219
|
// Internal state exposed for direct manipulation by safe response methods
|
|
194
220
|
// that need to bypass dd-trace interception of stream methods
|
|
195
221
|
this._chunks = [];
|
|
222
|
+
this._ended = false; // Track ended state since writableEnded is lost after prototype change
|
|
196
223
|
this._headers = new Map();
|
|
197
224
|
this._headersSent = false;
|
|
198
225
|
this._resolve = null;
|
|
@@ -201,6 +228,32 @@ class LambdaResponseBuffered extends Writable {
|
|
|
201
228
|
if (kOutHeaders$1) {
|
|
202
229
|
this[kOutHeaders$1] = Object.create(null);
|
|
203
230
|
}
|
|
231
|
+
// CRITICAL: Define key methods as instance properties to survive Express's
|
|
232
|
+
// setPrototypeOf(res, app.response) in middleware/init.js which would
|
|
233
|
+
// otherwise replace our prototype with ServerResponse.prototype.
|
|
234
|
+
// Instance properties take precedence over prototype properties.
|
|
235
|
+
this.getHeader = this.getHeader.bind(this);
|
|
236
|
+
this.setHeader = this.setHeader.bind(this);
|
|
237
|
+
this.removeHeader = this.removeHeader.bind(this);
|
|
238
|
+
this.hasHeader = this.hasHeader.bind(this);
|
|
239
|
+
this.getHeaders = this.getHeaders.bind(this);
|
|
240
|
+
this.getHeaderNames = this.getHeaderNames.bind(this);
|
|
241
|
+
this.writeHead = this.writeHead.bind(this);
|
|
242
|
+
this.get = this.get.bind(this);
|
|
243
|
+
this.set = this.set.bind(this);
|
|
244
|
+
this.status = this.status.bind(this);
|
|
245
|
+
this.json = this.json.bind(this);
|
|
246
|
+
this.send = this.send.bind(this);
|
|
247
|
+
this.vary = this.vary.bind(this);
|
|
248
|
+
this.end = this.end.bind(this);
|
|
249
|
+
this.write = this.write.bind(this);
|
|
250
|
+
// Also bind internal Writable methods that are called via prototype chain
|
|
251
|
+
this._write = this._write.bind(this);
|
|
252
|
+
this._final = this._final.bind(this);
|
|
253
|
+
// Bind result-building methods
|
|
254
|
+
this.getResult = this.getResult.bind(this);
|
|
255
|
+
this.buildResult = this.buildResult.bind(this);
|
|
256
|
+
this.isBinaryContentType = this.isBinaryContentType.bind(this);
|
|
204
257
|
}
|
|
205
258
|
//
|
|
206
259
|
// Internal bypass methods - completely avoid prototype chain lookup
|
|
@@ -243,7 +296,8 @@ class LambdaResponseBuffered extends Writable {
|
|
|
243
296
|
//
|
|
244
297
|
getResult() {
|
|
245
298
|
return new Promise((resolve) => {
|
|
246
|
-
|
|
299
|
+
// Use _ended instead of writableEnded since Express's setPrototypeOf breaks the getter
|
|
300
|
+
if (this._ended) {
|
|
247
301
|
resolve(this.buildResult());
|
|
248
302
|
}
|
|
249
303
|
else {
|
|
@@ -437,6 +491,7 @@ class LambdaResponseBuffered extends Writable {
|
|
|
437
491
|
callback();
|
|
438
492
|
}
|
|
439
493
|
_final(callback) {
|
|
494
|
+
this._ended = true;
|
|
440
495
|
if (this._resolve) {
|
|
441
496
|
this._resolve(this.buildResult());
|
|
442
497
|
}
|
|
@@ -522,6 +577,29 @@ class LambdaResponseStreaming extends Writable {
|
|
|
522
577
|
if (kOutHeaders) {
|
|
523
578
|
this[kOutHeaders] = Object.create(null);
|
|
524
579
|
}
|
|
580
|
+
// CRITICAL: Define key methods as instance properties to survive Express's
|
|
581
|
+
// setPrototypeOf(res, app.response) in middleware/init.js which would
|
|
582
|
+
// otherwise replace our prototype with ServerResponse.prototype.
|
|
583
|
+
// Instance properties take precedence over prototype properties.
|
|
584
|
+
this.getHeader = this.getHeader.bind(this);
|
|
585
|
+
this.setHeader = this.setHeader.bind(this);
|
|
586
|
+
this.removeHeader = this.removeHeader.bind(this);
|
|
587
|
+
this.hasHeader = this.hasHeader.bind(this);
|
|
588
|
+
this.getHeaders = this.getHeaders.bind(this);
|
|
589
|
+
this.getHeaderNames = this.getHeaderNames.bind(this);
|
|
590
|
+
this.writeHead = this.writeHead.bind(this);
|
|
591
|
+
this.flushHeaders = this.flushHeaders.bind(this);
|
|
592
|
+
this.get = this.get.bind(this);
|
|
593
|
+
this.set = this.set.bind(this);
|
|
594
|
+
this.status = this.status.bind(this);
|
|
595
|
+
this.json = this.json.bind(this);
|
|
596
|
+
this.send = this.send.bind(this);
|
|
597
|
+
this.vary = this.vary.bind(this);
|
|
598
|
+
this.end = this.end.bind(this);
|
|
599
|
+
this.write = this.write.bind(this);
|
|
600
|
+
// Also bind internal Writable methods that are called via prototype chain
|
|
601
|
+
this._write = this._write.bind(this);
|
|
602
|
+
this._final = this._final.bind(this);
|
|
525
603
|
}
|
|
526
604
|
//
|
|
527
605
|
// Internal bypass methods - completely avoid prototype chain lookup
|
|
@@ -1716,12 +1794,12 @@ function expressHandler(handlerOrOptions, optionsOrHandler) {
|
|
|
1716
1794
|
}
|
|
1717
1795
|
}
|
|
1718
1796
|
catch (error) {
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
if (error instanceof Error && error.stack) {
|
|
1723
|
-
log.error(error.stack);
|
|
1797
|
+
// Use console.error for raw stack trace to ensure it appears in CloudWatch
|
|
1798
|
+
if (error instanceof Error) {
|
|
1799
|
+
console.error("Express response error stack trace:", error.stack);
|
|
1724
1800
|
}
|
|
1801
|
+
log.fatal(`Express encountered an error while sending the response: ${error instanceof Error ? error.message : String(error)}`);
|
|
1802
|
+
log.var({ responseError: error });
|
|
1725
1803
|
}
|
|
1726
1804
|
// Log response
|
|
1727
1805
|
const extras = {};
|