@jaypie/express 1.2.4-rc14 → 1.2.4-rc15

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.
@@ -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 {};
@@ -34,6 +34,15 @@ class LambdaRequest extends node_stream.Readable {
34
34
  this.path = options.url.split("?")[0];
35
35
  this.headers = this.normalizeHeaders(options.headers);
36
36
  this.bodyBuffer = options.body ?? null;
37
+ // Parse query string from URL
38
+ const queryIndex = options.url.indexOf("?");
39
+ if (queryIndex !== -1) {
40
+ const queryString = options.url.slice(queryIndex + 1);
41
+ const params = new URLSearchParams(queryString);
42
+ for (const [key, value] of params) {
43
+ this.query[key] = value;
44
+ }
45
+ }
37
46
  // Store Lambda context
38
47
  this._lambdaContext = options.lambdaContext;
39
48
  this._lambdaEvent = options.lambdaEvent;
@@ -44,6 +53,18 @@ class LambdaRequest extends node_stream.Readable {
44
53
  remoteAddress: options.remoteAddress,
45
54
  };
46
55
  this.connection = this.socket;
56
+ // Schedule body push for next tick to ensure stream is ready
57
+ // This is needed for body parsers that consume the stream
58
+ if (this.bodyBuffer && this.bodyBuffer.length > 0) {
59
+ process.nextTick(() => {
60
+ if (!this.bodyPushed) {
61
+ this.push(this.bodyBuffer);
62
+ this.push(null);
63
+ this.bodyPushed = true;
64
+ this.complete = true;
65
+ }
66
+ });
67
+ }
47
68
  }
48
69
  //
49
70
  // Readable stream implementation
@@ -145,6 +166,11 @@ function createLambdaRequest(event, context) {
145
166
  body = event.isBase64Encoded
146
167
  ? Buffer.from(event.body, "base64")
147
168
  : Buffer.from(event.body, "utf8");
169
+ // Add content-length header if not present (required for body parsers)
170
+ const hasContentLength = Object.keys(headers).some((k) => k.toLowerCase() === "content-length");
171
+ if (!hasContentLength) {
172
+ headers["content-length"] = String(body.length);
173
+ }
148
174
  }
149
175
  return new LambdaRequest({
150
176
  body,
@@ -195,6 +221,7 @@ class LambdaResponseBuffered extends node_stream.Writable {
195
221
  // Internal state exposed for direct manipulation by safe response methods
196
222
  // that need to bypass dd-trace interception of stream methods
197
223
  this._chunks = [];
224
+ this._ended = false; // Track ended state since writableEnded is lost after prototype change
198
225
  this._headers = new Map();
199
226
  this._headersSent = false;
200
227
  this._resolve = null;
@@ -203,6 +230,32 @@ class LambdaResponseBuffered extends node_stream.Writable {
203
230
  if (kOutHeaders$1) {
204
231
  this[kOutHeaders$1] = Object.create(null);
205
232
  }
233
+ // CRITICAL: Define key methods as instance properties to survive Express's
234
+ // setPrototypeOf(res, app.response) in middleware/init.js which would
235
+ // otherwise replace our prototype with ServerResponse.prototype.
236
+ // Instance properties take precedence over prototype properties.
237
+ this.getHeader = this.getHeader.bind(this);
238
+ this.setHeader = this.setHeader.bind(this);
239
+ this.removeHeader = this.removeHeader.bind(this);
240
+ this.hasHeader = this.hasHeader.bind(this);
241
+ this.getHeaders = this.getHeaders.bind(this);
242
+ this.getHeaderNames = this.getHeaderNames.bind(this);
243
+ this.writeHead = this.writeHead.bind(this);
244
+ this.get = this.get.bind(this);
245
+ this.set = this.set.bind(this);
246
+ this.status = this.status.bind(this);
247
+ this.json = this.json.bind(this);
248
+ this.send = this.send.bind(this);
249
+ this.vary = this.vary.bind(this);
250
+ this.end = this.end.bind(this);
251
+ this.write = this.write.bind(this);
252
+ // Also bind internal Writable methods that are called via prototype chain
253
+ this._write = this._write.bind(this);
254
+ this._final = this._final.bind(this);
255
+ // Bind result-building methods
256
+ this.getResult = this.getResult.bind(this);
257
+ this.buildResult = this.buildResult.bind(this);
258
+ this.isBinaryContentType = this.isBinaryContentType.bind(this);
206
259
  }
207
260
  //
208
261
  // Internal bypass methods - completely avoid prototype chain lookup
@@ -245,7 +298,8 @@ class LambdaResponseBuffered extends node_stream.Writable {
245
298
  //
246
299
  getResult() {
247
300
  return new Promise((resolve) => {
248
- if (this.writableEnded) {
301
+ // Use _ended instead of writableEnded since Express's setPrototypeOf breaks the getter
302
+ if (this._ended) {
249
303
  resolve(this.buildResult());
250
304
  }
251
305
  else {
@@ -439,6 +493,7 @@ class LambdaResponseBuffered extends node_stream.Writable {
439
493
  callback();
440
494
  }
441
495
  _final(callback) {
496
+ this._ended = true;
442
497
  if (this._resolve) {
443
498
  this._resolve(this.buildResult());
444
499
  }
@@ -524,6 +579,29 @@ class LambdaResponseStreaming extends node_stream.Writable {
524
579
  if (kOutHeaders) {
525
580
  this[kOutHeaders] = Object.create(null);
526
581
  }
582
+ // CRITICAL: Define key methods as instance properties to survive Express's
583
+ // setPrototypeOf(res, app.response) in middleware/init.js which would
584
+ // otherwise replace our prototype with ServerResponse.prototype.
585
+ // Instance properties take precedence over prototype properties.
586
+ this.getHeader = this.getHeader.bind(this);
587
+ this.setHeader = this.setHeader.bind(this);
588
+ this.removeHeader = this.removeHeader.bind(this);
589
+ this.hasHeader = this.hasHeader.bind(this);
590
+ this.getHeaders = this.getHeaders.bind(this);
591
+ this.getHeaderNames = this.getHeaderNames.bind(this);
592
+ this.writeHead = this.writeHead.bind(this);
593
+ this.flushHeaders = this.flushHeaders.bind(this);
594
+ this.get = this.get.bind(this);
595
+ this.set = this.set.bind(this);
596
+ this.status = this.status.bind(this);
597
+ this.json = this.json.bind(this);
598
+ this.send = this.send.bind(this);
599
+ this.vary = this.vary.bind(this);
600
+ this.end = this.end.bind(this);
601
+ this.write = this.write.bind(this);
602
+ // Also bind internal Writable methods that are called via prototype chain
603
+ this._write = this._write.bind(this);
604
+ this._final = this._final.bind(this);
527
605
  }
528
606
  //
529
607
  // Internal bypass methods - completely avoid prototype chain lookup