@jaypie/express 1.2.32 → 1.2.34
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 +7 -0
- package/dist/cjs/adapter/LambdaResponseStreaming.d.ts +8 -0
- package/dist/cjs/adapter/headers.helper.d.ts +15 -0
- package/dist/cjs/adapter/types.d.ts +1 -0
- package/dist/cjs/index.cjs +98 -34
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +15 -0
- package/dist/esm/adapter/LambdaResponseBuffered.d.ts +7 -0
- package/dist/esm/adapter/LambdaResponseStreaming.d.ts +8 -0
- package/dist/esm/adapter/headers.helper.d.ts +15 -0
- package/dist/esm/adapter/types.d.ts +1 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.js +98 -34
- package/dist/esm/index.js.map +1 -1
- package/package.json +3 -1
package/dist/cjs/index.d.cts
CHANGED
|
@@ -178,6 +178,13 @@ declare class LambdaResponseBuffered extends Writable {
|
|
|
178
178
|
*/
|
|
179
179
|
get headers(): Record<string, string | string[] | undefined>;
|
|
180
180
|
writeHead(statusCode: number, statusMessageOrHeaders?: OutgoingHttpHeaders | string, headers?: OutgoingHttpHeaders): this;
|
|
181
|
+
/**
|
|
182
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
183
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
184
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
185
|
+
* compression, express-openid-connect) run their listeners.
|
|
186
|
+
*/
|
|
187
|
+
_implicitHeader(): void;
|
|
181
188
|
get headersSent(): boolean;
|
|
182
189
|
/**
|
|
183
190
|
* Express-style alias for getHeader().
|
|
@@ -241,8 +248,16 @@ declare class LambdaResponseStreaming extends Writable {
|
|
|
241
248
|
*/
|
|
242
249
|
get headers(): Record<string, string | string[] | undefined>;
|
|
243
250
|
writeHead(statusCode: number, statusMessageOrHeaders?: OutgoingHttpHeaders | string, headers?: OutgoingHttpHeaders): this;
|
|
251
|
+
/**
|
|
252
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
253
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
254
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
255
|
+
* compression, express-openid-connect) run their listeners.
|
|
256
|
+
*/
|
|
257
|
+
_implicitHeader(): void;
|
|
244
258
|
get headersSent(): boolean;
|
|
245
259
|
flushHeaders(): void;
|
|
260
|
+
private _commitHeaders;
|
|
246
261
|
/**
|
|
247
262
|
* Express-style alias for getHeader().
|
|
248
263
|
* Used by middleware like decorateResponse that use res.get().
|
|
@@ -36,6 +36,13 @@ export declare class LambdaResponseBuffered extends Writable {
|
|
|
36
36
|
*/
|
|
37
37
|
get headers(): Record<string, string | string[] | undefined>;
|
|
38
38
|
writeHead(statusCode: number, statusMessageOrHeaders?: OutgoingHttpHeaders | string, headers?: OutgoingHttpHeaders): this;
|
|
39
|
+
/**
|
|
40
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
41
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
42
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
43
|
+
* compression, express-openid-connect) run their listeners.
|
|
44
|
+
*/
|
|
45
|
+
_implicitHeader(): void;
|
|
39
46
|
get headersSent(): boolean;
|
|
40
47
|
/**
|
|
41
48
|
* Express-style alias for getHeader().
|
|
@@ -36,8 +36,16 @@ export declare class LambdaResponseStreaming extends Writable {
|
|
|
36
36
|
*/
|
|
37
37
|
get headers(): Record<string, string | string[] | undefined>;
|
|
38
38
|
writeHead(statusCode: number, statusMessageOrHeaders?: OutgoingHttpHeaders | string, headers?: OutgoingHttpHeaders): this;
|
|
39
|
+
/**
|
|
40
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
41
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
42
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
43
|
+
* compression, express-openid-connect) run their listeners.
|
|
44
|
+
*/
|
|
45
|
+
_implicitHeader(): void;
|
|
39
46
|
get headersSent(): boolean;
|
|
40
47
|
flushHeaders(): void;
|
|
48
|
+
private _commitHeaders;
|
|
41
49
|
/**
|
|
42
50
|
* Express-style alias for getHeader().
|
|
43
51
|
* Used by middleware like decorateResponse that use res.get().
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare const SET_COOKIE = "set-cookie";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize a header value for storage, preserving arrays.
|
|
4
|
+
* Node's ServerResponse keeps multi-value headers as arrays; stringifying
|
|
5
|
+
* here would fold them into a single comma-separated value.
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeHeaderValue(value: number | string | string[]): string | string[];
|
|
8
|
+
/**
|
|
9
|
+
* Split stored headers into a single-value header record and a cookies
|
|
10
|
+
* array, matching the Lambda Function URL (v2) response shape.
|
|
11
|
+
*/
|
|
12
|
+
export declare function splitCookieHeaders(source: Map<string, string | string[]>): {
|
|
13
|
+
cookies: string[];
|
|
14
|
+
headers: Record<string, string>;
|
|
15
|
+
};
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -178,6 +178,13 @@ declare class LambdaResponseBuffered extends Writable {
|
|
|
178
178
|
*/
|
|
179
179
|
get headers(): Record<string, string | string[] | undefined>;
|
|
180
180
|
writeHead(statusCode: number, statusMessageOrHeaders?: OutgoingHttpHeaders | string, headers?: OutgoingHttpHeaders): this;
|
|
181
|
+
/**
|
|
182
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
183
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
184
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
185
|
+
* compression, express-openid-connect) run their listeners.
|
|
186
|
+
*/
|
|
187
|
+
_implicitHeader(): void;
|
|
181
188
|
get headersSent(): boolean;
|
|
182
189
|
/**
|
|
183
190
|
* Express-style alias for getHeader().
|
|
@@ -241,8 +248,16 @@ declare class LambdaResponseStreaming extends Writable {
|
|
|
241
248
|
*/
|
|
242
249
|
get headers(): Record<string, string | string[] | undefined>;
|
|
243
250
|
writeHead(statusCode: number, statusMessageOrHeaders?: OutgoingHttpHeaders | string, headers?: OutgoingHttpHeaders): this;
|
|
251
|
+
/**
|
|
252
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
253
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
254
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
255
|
+
* compression, express-openid-connect) run their listeners.
|
|
256
|
+
*/
|
|
257
|
+
_implicitHeader(): void;
|
|
244
258
|
get headersSent(): boolean;
|
|
245
259
|
flushHeaders(): void;
|
|
260
|
+
private _commitHeaders;
|
|
246
261
|
/**
|
|
247
262
|
* Express-style alias for getHeader().
|
|
248
263
|
* Used by middleware like decorateResponse that use res.get().
|
package/dist/esm/index.js
CHANGED
|
@@ -276,6 +276,50 @@ function createLambdaRequest(event, context) {
|
|
|
276
276
|
});
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
+
//
|
|
280
|
+
//
|
|
281
|
+
// Constants
|
|
282
|
+
//
|
|
283
|
+
// Set-Cookie is the one header that must never be comma-folded: cookie
|
|
284
|
+
// expiry dates contain commas, so a folded value is unparseable. Lambda
|
|
285
|
+
// carries these out-of-band in the `cookies` field of the v2 response
|
|
286
|
+
// payload and of the response-streaming metadata prelude.
|
|
287
|
+
const SET_COOKIE = "set-cookie";
|
|
288
|
+
//
|
|
289
|
+
//
|
|
290
|
+
// Functions
|
|
291
|
+
//
|
|
292
|
+
/**
|
|
293
|
+
* Normalize a header value for storage, preserving arrays.
|
|
294
|
+
* Node's ServerResponse keeps multi-value headers as arrays; stringifying
|
|
295
|
+
* here would fold them into a single comma-separated value.
|
|
296
|
+
*/
|
|
297
|
+
function normalizeHeaderValue(value) {
|
|
298
|
+
return Array.isArray(value) ? value.map(String) : String(value);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Split stored headers into a single-value header record and a cookies
|
|
302
|
+
* array, matching the Lambda Function URL (v2) response shape.
|
|
303
|
+
*/
|
|
304
|
+
function splitCookieHeaders(source) {
|
|
305
|
+
const cookies = [];
|
|
306
|
+
const headers = {};
|
|
307
|
+
for (const [key, value] of source) {
|
|
308
|
+
if (key === SET_COOKIE) {
|
|
309
|
+
if (Array.isArray(value)) {
|
|
310
|
+
cookies.push(...value);
|
|
311
|
+
}
|
|
312
|
+
else {
|
|
313
|
+
cookies.push(value);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
headers[key] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
return { cookies, headers };
|
|
321
|
+
}
|
|
322
|
+
|
|
279
323
|
//
|
|
280
324
|
//
|
|
281
325
|
// Constants
|
|
@@ -338,6 +382,7 @@ class LambdaResponseBuffered extends Writable {
|
|
|
338
382
|
this.getHeaders = this.getHeaders.bind(this);
|
|
339
383
|
this.getHeaderNames = this.getHeaderNames.bind(this);
|
|
340
384
|
this.writeHead = this.writeHead.bind(this);
|
|
385
|
+
this._implicitHeader = this._implicitHeader.bind(this);
|
|
341
386
|
this.get = this.get.bind(this);
|
|
342
387
|
this.set = this.set.bind(this);
|
|
343
388
|
this.status = this.status.bind(this);
|
|
@@ -413,13 +458,14 @@ class LambdaResponseBuffered extends Writable {
|
|
|
413
458
|
return this;
|
|
414
459
|
}
|
|
415
460
|
const lowerName = name.toLowerCase();
|
|
416
|
-
|
|
461
|
+
const normalized = normalizeHeaderValue(value);
|
|
462
|
+
this._headers.set(lowerName, normalized);
|
|
417
463
|
// Sync with kOutHeaders for dd-trace compatibility
|
|
418
464
|
// Node stores as { 'header-name': ['Header-Name', value] }
|
|
419
465
|
if (kOutHeaders$1) {
|
|
420
466
|
const outHeaders = this[kOutHeaders$1];
|
|
421
467
|
if (outHeaders) {
|
|
422
|
-
outHeaders[lowerName] = [name,
|
|
468
|
+
outHeaders[lowerName] = [name, normalized];
|
|
423
469
|
}
|
|
424
470
|
}
|
|
425
471
|
return this;
|
|
@@ -493,6 +539,9 @@ class LambdaResponseBuffered extends Writable {
|
|
|
493
539
|
});
|
|
494
540
|
}
|
|
495
541
|
writeHead(statusCode, statusMessageOrHeaders, headers) {
|
|
542
|
+
if (this._headersSent) {
|
|
543
|
+
return this;
|
|
544
|
+
}
|
|
496
545
|
this.statusCode = statusCode;
|
|
497
546
|
let headersToSet;
|
|
498
547
|
if (typeof statusMessageOrHeaders === "string") {
|
|
@@ -507,13 +556,24 @@ class LambdaResponseBuffered extends Writable {
|
|
|
507
556
|
// Use direct _headers access to bypass dd-trace interception
|
|
508
557
|
for (const [key, value] of Object.entries(headersToSet)) {
|
|
509
558
|
if (value !== undefined) {
|
|
510
|
-
this._headers.set(key.toLowerCase(),
|
|
559
|
+
this._headers.set(key.toLowerCase(), normalizeHeaderValue(value));
|
|
511
560
|
}
|
|
512
561
|
}
|
|
513
562
|
}
|
|
514
563
|
this._headersSent = true;
|
|
515
564
|
return this;
|
|
516
565
|
}
|
|
566
|
+
/**
|
|
567
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
568
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
569
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
570
|
+
* compression, express-openid-connect) run their listeners.
|
|
571
|
+
*/
|
|
572
|
+
_implicitHeader() {
|
|
573
|
+
if (!this._headersSent) {
|
|
574
|
+
this.writeHead(this.statusCode);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
517
577
|
get headersSent() {
|
|
518
578
|
return this._headersSent;
|
|
519
579
|
}
|
|
@@ -535,7 +595,7 @@ class LambdaResponseBuffered extends Writable {
|
|
|
535
595
|
*/
|
|
536
596
|
set(name, value) {
|
|
537
597
|
if (!this._headersSent) {
|
|
538
|
-
this._headers.set(name.toLowerCase(),
|
|
598
|
+
this._headers.set(name.toLowerCase(), normalizeHeaderValue(value));
|
|
539
599
|
}
|
|
540
600
|
return this;
|
|
541
601
|
}
|
|
@@ -585,11 +645,13 @@ class LambdaResponseBuffered extends Writable {
|
|
|
585
645
|
const buffer = Buffer.isBuffer(chunk)
|
|
586
646
|
? chunk
|
|
587
647
|
: Buffer.from(chunk, encoding);
|
|
648
|
+
this._implicitHeader();
|
|
588
649
|
this._chunks.push(buffer);
|
|
589
650
|
this._headersSent = true;
|
|
590
651
|
callback();
|
|
591
652
|
}
|
|
592
653
|
_final(callback) {
|
|
654
|
+
this._implicitHeader();
|
|
593
655
|
this._ended = true;
|
|
594
656
|
if (this._resolve) {
|
|
595
657
|
this._resolve(this.buildResult());
|
|
@@ -605,23 +667,8 @@ class LambdaResponseBuffered extends Writable {
|
|
|
605
667
|
const contentType = this._headers.get("content-type") || "";
|
|
606
668
|
// Determine if response should be base64 encoded
|
|
607
669
|
const isBase64Encoded = this.isBinaryContentType(contentType);
|
|
608
|
-
// Build headers object
|
|
609
|
-
const headers =
|
|
610
|
-
const cookies = [];
|
|
611
|
-
for (const [key, value] of this._headers) {
|
|
612
|
-
if (key === "set-cookie") {
|
|
613
|
-
// Collect Set-Cookie headers for v2 response format
|
|
614
|
-
if (Array.isArray(value)) {
|
|
615
|
-
cookies.push(...value);
|
|
616
|
-
}
|
|
617
|
-
else {
|
|
618
|
-
cookies.push(value);
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
else {
|
|
622
|
-
headers[key] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
623
|
-
}
|
|
624
|
-
}
|
|
670
|
+
// Build headers object, carrying Set-Cookie out-of-band (v2 format)
|
|
671
|
+
const { cookies, headers } = splitCookieHeaders(this._headers);
|
|
625
672
|
const result = {
|
|
626
673
|
body: isBase64Encoded ? body.toString("base64") : body.toString("utf8"),
|
|
627
674
|
headers,
|
|
@@ -696,6 +743,8 @@ class LambdaResponseStreaming extends Writable {
|
|
|
696
743
|
this.getHeaderNames = this.getHeaderNames.bind(this);
|
|
697
744
|
this.writeHead = this.writeHead.bind(this);
|
|
698
745
|
this.flushHeaders = this.flushHeaders.bind(this);
|
|
746
|
+
this._implicitHeader = this._implicitHeader.bind(this);
|
|
747
|
+
this._commitHeaders = this._commitHeaders.bind(this);
|
|
699
748
|
this.get = this.get.bind(this);
|
|
700
749
|
this.set = this.set.bind(this);
|
|
701
750
|
this.status = this.status.bind(this);
|
|
@@ -754,13 +803,14 @@ class LambdaResponseStreaming extends Writable {
|
|
|
754
803
|
return this;
|
|
755
804
|
}
|
|
756
805
|
const lowerName = name.toLowerCase();
|
|
757
|
-
|
|
806
|
+
const normalized = normalizeHeaderValue(value);
|
|
807
|
+
this._headers.set(lowerName, normalized);
|
|
758
808
|
// Sync with kOutHeaders for dd-trace compatibility
|
|
759
809
|
// Node stores as { 'header-name': ['Header-Name', value] }
|
|
760
810
|
if (kOutHeaders) {
|
|
761
811
|
const outHeaders = this[kOutHeaders];
|
|
762
812
|
if (outHeaders) {
|
|
763
|
-
outHeaders[lowerName] = [name,
|
|
813
|
+
outHeaders[lowerName] = [name, normalized];
|
|
764
814
|
}
|
|
765
815
|
}
|
|
766
816
|
return this;
|
|
@@ -855,24 +905,36 @@ class LambdaResponseStreaming extends Writable {
|
|
|
855
905
|
// Use direct _headers access to bypass dd-trace interception
|
|
856
906
|
for (const [key, value] of Object.entries(headersToSet)) {
|
|
857
907
|
if (value !== undefined) {
|
|
858
|
-
this._headers.set(key.toLowerCase(),
|
|
908
|
+
this._headers.set(key.toLowerCase(), normalizeHeaderValue(value));
|
|
859
909
|
}
|
|
860
910
|
}
|
|
861
911
|
}
|
|
862
|
-
this.
|
|
912
|
+
this._commitHeaders();
|
|
863
913
|
return this;
|
|
864
914
|
}
|
|
915
|
+
/**
|
|
916
|
+
* Node's implicit-header hook, called before the first body byte commits.
|
|
917
|
+
* Routes through this.writeHead resolved at call time so wrappers installed
|
|
918
|
+
* mid-request (on-headers, and through it express-session, morgan,
|
|
919
|
+
* compression, express-openid-connect) run their listeners.
|
|
920
|
+
*/
|
|
921
|
+
_implicitHeader() {
|
|
922
|
+
if (!this._headersSent) {
|
|
923
|
+
this.writeHead(this.statusCode);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
865
926
|
get headersSent() {
|
|
866
927
|
return this._headersSent;
|
|
867
928
|
}
|
|
868
929
|
flushHeaders() {
|
|
930
|
+
this._implicitHeader();
|
|
931
|
+
}
|
|
932
|
+
_commitHeaders() {
|
|
869
933
|
if (this._headersSent) {
|
|
870
934
|
return;
|
|
871
935
|
}
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
headers[key] = Array.isArray(value) ? value.join(", ") : String(value);
|
|
875
|
-
}
|
|
936
|
+
// Set-Cookie travels in metadata.cookies, never folded into headers
|
|
937
|
+
const { cookies, headers } = splitCookieHeaders(this._headers);
|
|
876
938
|
// Lambda streaming requires body content for metadata to be transmitted.
|
|
877
939
|
// Convert 204 No Content to 200 OK with empty JSON body as workaround.
|
|
878
940
|
// See: https://github.com/finlaysonstudio/jaypie/issues/178
|
|
@@ -887,6 +949,10 @@ class LambdaResponseStreaming extends Writable {
|
|
|
887
949
|
headers,
|
|
888
950
|
statusCode,
|
|
889
951
|
};
|
|
952
|
+
// Only include cookies if present (v2 format)
|
|
953
|
+
if (cookies.length > 0) {
|
|
954
|
+
metadata.cookies = cookies;
|
|
955
|
+
}
|
|
890
956
|
// Create wrapped stream with metadata
|
|
891
957
|
this._wrappedStream = awslambda.HttpResponseStream.from(this._responseStream, metadata);
|
|
892
958
|
this._headersSent = true;
|
|
@@ -915,7 +981,7 @@ class LambdaResponseStreaming extends Writable {
|
|
|
915
981
|
*/
|
|
916
982
|
set(name, value) {
|
|
917
983
|
if (!this._headersSent) {
|
|
918
|
-
this._headers.set(name.toLowerCase(),
|
|
984
|
+
this._headers.set(name.toLowerCase(), normalizeHeaderValue(value));
|
|
919
985
|
}
|
|
920
986
|
return this;
|
|
921
987
|
}
|
|
@@ -969,7 +1035,7 @@ class LambdaResponseStreaming extends Writable {
|
|
|
969
1035
|
// Buffer writes until headers are sent
|
|
970
1036
|
this._pendingWrites.push({ callback: () => callback(), chunk: buffer });
|
|
971
1037
|
// Auto-flush headers on first write
|
|
972
|
-
this.
|
|
1038
|
+
this._implicitHeader();
|
|
973
1039
|
}
|
|
974
1040
|
else {
|
|
975
1041
|
this._wrappedStream.write(buffer);
|
|
@@ -977,9 +1043,7 @@ class LambdaResponseStreaming extends Writable {
|
|
|
977
1043
|
}
|
|
978
1044
|
}
|
|
979
1045
|
_final(callback) {
|
|
980
|
-
|
|
981
|
-
this.flushHeaders();
|
|
982
|
-
}
|
|
1046
|
+
this._implicitHeader();
|
|
983
1047
|
// For converted 204 responses, write empty JSON body
|
|
984
1048
|
// Lambda streaming requires body content for metadata to be transmitted
|
|
985
1049
|
if (this._convertedFrom204 && this._wrappedStream) {
|