@jaypie/express 1.2.4-rc5 → 1.2.4-rc7
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/index.cjs +128 -12
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +128 -12
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var node_stream = require('node:stream');
|
|
4
|
+
var node_http = require('node:http');
|
|
4
5
|
var errors = require('@jaypie/errors');
|
|
5
6
|
var kit = require('@jaypie/kit');
|
|
6
7
|
var expressCors = require('cors');
|
|
@@ -161,6 +162,10 @@ function createLambdaRequest(event, context) {
|
|
|
161
162
|
//
|
|
162
163
|
// Constants
|
|
163
164
|
//
|
|
165
|
+
// Get Node's internal kOutHeaders symbol from ServerResponse prototype.
|
|
166
|
+
// This is needed for compatibility with Datadog dd-trace instrumentation,
|
|
167
|
+
// which patches HTTP methods and expects this internal state to exist.
|
|
168
|
+
const kOutHeaders$1 = Object.getOwnPropertySymbols(node_http.ServerResponse.prototype).find((s) => s.toString() === "Symbol(kOutHeaders)");
|
|
164
169
|
const BINARY_CONTENT_TYPE_PATTERNS = [
|
|
165
170
|
/^application\/octet-stream$/,
|
|
166
171
|
/^application\/pdf$/,
|
|
@@ -191,6 +196,11 @@ class LambdaResponseBuffered extends node_stream.Writable {
|
|
|
191
196
|
this._headers = new Map();
|
|
192
197
|
this._headersSent = false;
|
|
193
198
|
this._resolve = null;
|
|
199
|
+
// Initialize Node's internal kOutHeaders for dd-trace compatibility.
|
|
200
|
+
// dd-trace patches HTTP methods and expects this internal state.
|
|
201
|
+
if (kOutHeaders$1) {
|
|
202
|
+
this[kOutHeaders$1] = Object.create(null);
|
|
203
|
+
}
|
|
194
204
|
}
|
|
195
205
|
//
|
|
196
206
|
// Promise-based API for getting final result
|
|
@@ -213,14 +223,31 @@ class LambdaResponseBuffered extends node_stream.Writable {
|
|
|
213
223
|
// In production, log warning but don't throw to match Express behavior
|
|
214
224
|
return this;
|
|
215
225
|
}
|
|
216
|
-
|
|
226
|
+
const lowerName = name.toLowerCase();
|
|
227
|
+
this._headers.set(lowerName, String(value));
|
|
228
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
229
|
+
// Node stores as { 'header-name': ['Header-Name', value] }
|
|
230
|
+
if (kOutHeaders$1) {
|
|
231
|
+
const outHeaders = this[kOutHeaders$1];
|
|
232
|
+
if (outHeaders) {
|
|
233
|
+
outHeaders[lowerName] = [name, String(value)];
|
|
234
|
+
}
|
|
235
|
+
}
|
|
217
236
|
return this;
|
|
218
237
|
}
|
|
219
238
|
getHeader(name) {
|
|
220
239
|
return this._headers.get(name.toLowerCase());
|
|
221
240
|
}
|
|
222
241
|
removeHeader(name) {
|
|
223
|
-
|
|
242
|
+
const lowerName = name.toLowerCase();
|
|
243
|
+
this._headers.delete(lowerName);
|
|
244
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
245
|
+
if (kOutHeaders$1) {
|
|
246
|
+
const outHeaders = this[kOutHeaders$1];
|
|
247
|
+
if (outHeaders) {
|
|
248
|
+
delete outHeaders[lowerName];
|
|
249
|
+
}
|
|
250
|
+
}
|
|
224
251
|
}
|
|
225
252
|
getHeaders() {
|
|
226
253
|
const headers = {};
|
|
@@ -414,6 +441,14 @@ class LambdaResponseBuffered extends node_stream.Writable {
|
|
|
414
441
|
}
|
|
415
442
|
}
|
|
416
443
|
|
|
444
|
+
//
|
|
445
|
+
//
|
|
446
|
+
// Constants
|
|
447
|
+
//
|
|
448
|
+
// Get Node's internal kOutHeaders symbol from ServerResponse prototype.
|
|
449
|
+
// This is needed for compatibility with Datadog dd-trace instrumentation,
|
|
450
|
+
// which patches HTTP methods and expects this internal state to exist.
|
|
451
|
+
const kOutHeaders = Object.getOwnPropertySymbols(node_http.ServerResponse.prototype).find((s) => s.toString() === "Symbol(kOutHeaders)");
|
|
417
452
|
//
|
|
418
453
|
//
|
|
419
454
|
// LambdaResponseStreaming Class
|
|
@@ -436,6 +471,11 @@ class LambdaResponseStreaming extends node_stream.Writable {
|
|
|
436
471
|
this._pendingWrites = [];
|
|
437
472
|
this._wrappedStream = null;
|
|
438
473
|
this._responseStream = responseStream;
|
|
474
|
+
// Initialize Node's internal kOutHeaders for dd-trace compatibility.
|
|
475
|
+
// dd-trace patches HTTP methods and expects this internal state.
|
|
476
|
+
if (kOutHeaders) {
|
|
477
|
+
this[kOutHeaders] = Object.create(null);
|
|
478
|
+
}
|
|
439
479
|
}
|
|
440
480
|
//
|
|
441
481
|
// Header management
|
|
@@ -446,7 +486,16 @@ class LambdaResponseStreaming extends node_stream.Writable {
|
|
|
446
486
|
// Headers cannot be changed after body starts
|
|
447
487
|
return this;
|
|
448
488
|
}
|
|
449
|
-
|
|
489
|
+
const lowerName = name.toLowerCase();
|
|
490
|
+
this._headers.set(lowerName, String(value));
|
|
491
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
492
|
+
// Node stores as { 'header-name': ['Header-Name', value] }
|
|
493
|
+
if (kOutHeaders) {
|
|
494
|
+
const outHeaders = this[kOutHeaders];
|
|
495
|
+
if (outHeaders) {
|
|
496
|
+
outHeaders[lowerName] = [name, String(value)];
|
|
497
|
+
}
|
|
498
|
+
}
|
|
450
499
|
return this;
|
|
451
500
|
}
|
|
452
501
|
getHeader(name) {
|
|
@@ -454,7 +503,15 @@ class LambdaResponseStreaming extends node_stream.Writable {
|
|
|
454
503
|
}
|
|
455
504
|
removeHeader(name) {
|
|
456
505
|
if (!this._headersSent) {
|
|
457
|
-
|
|
506
|
+
const lowerName = name.toLowerCase();
|
|
507
|
+
this._headers.delete(lowerName);
|
|
508
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
509
|
+
if (kOutHeaders) {
|
|
510
|
+
const outHeaders = this[kOutHeaders];
|
|
511
|
+
if (outHeaders) {
|
|
512
|
+
delete outHeaders[lowerName];
|
|
513
|
+
}
|
|
514
|
+
}
|
|
458
515
|
}
|
|
459
516
|
}
|
|
460
517
|
getHeaders() {
|
|
@@ -1069,6 +1126,64 @@ function getCurrentInvokeUuid(req) {
|
|
|
1069
1126
|
return getWebAdapterUuid();
|
|
1070
1127
|
}
|
|
1071
1128
|
|
|
1129
|
+
//
|
|
1130
|
+
//
|
|
1131
|
+
// Helpers
|
|
1132
|
+
//
|
|
1133
|
+
/**
|
|
1134
|
+
* Safely get a header value from response.
|
|
1135
|
+
* Handles both Express Response and Lambda adapter responses.
|
|
1136
|
+
* Defensive against dd-trace instrumentation issues.
|
|
1137
|
+
*/
|
|
1138
|
+
function safeGetHeader(res, name) {
|
|
1139
|
+
try {
|
|
1140
|
+
// Try direct _headers access first (Lambda adapter, avoids dd-trace)
|
|
1141
|
+
if (res._headers instanceof Map) {
|
|
1142
|
+
const value = res._headers.get(name.toLowerCase());
|
|
1143
|
+
return value ? String(value) : undefined;
|
|
1144
|
+
}
|
|
1145
|
+
// Fall back to getHeader (more standard than get)
|
|
1146
|
+
if (typeof res.getHeader === "function") {
|
|
1147
|
+
const value = res.getHeader(name);
|
|
1148
|
+
return value ? String(value) : undefined;
|
|
1149
|
+
}
|
|
1150
|
+
// Last resort: try get
|
|
1151
|
+
if (typeof res.get === "function") {
|
|
1152
|
+
const value = res.get(name);
|
|
1153
|
+
return value ? String(value) : undefined;
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
catch {
|
|
1157
|
+
// Silently fail - caller will handle missing value
|
|
1158
|
+
}
|
|
1159
|
+
return undefined;
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* Safely set a header value on response.
|
|
1163
|
+
* Handles both Express Response and Lambda adapter responses.
|
|
1164
|
+
* Defensive against dd-trace instrumentation issues.
|
|
1165
|
+
*/
|
|
1166
|
+
function safeSetHeader(res, name, value) {
|
|
1167
|
+
try {
|
|
1168
|
+
// Try direct _headers access first (Lambda adapter, avoids dd-trace)
|
|
1169
|
+
if (res._headers instanceof Map) {
|
|
1170
|
+
res._headers.set(name.toLowerCase(), value);
|
|
1171
|
+
return;
|
|
1172
|
+
}
|
|
1173
|
+
// Fall back to setHeader (more standard than set)
|
|
1174
|
+
if (typeof res.setHeader === "function") {
|
|
1175
|
+
res.setHeader(name, value);
|
|
1176
|
+
return;
|
|
1177
|
+
}
|
|
1178
|
+
// Last resort: try set
|
|
1179
|
+
if (typeof res.set === "function") {
|
|
1180
|
+
res.set(name, value);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
catch {
|
|
1184
|
+
// Silently fail - header just won't be set
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1072
1187
|
//
|
|
1073
1188
|
//
|
|
1074
1189
|
// Main
|
|
@@ -1085,36 +1200,37 @@ const decorateResponse = (res, { handler = "", version = process.env.PROJECT_VER
|
|
|
1085
1200
|
log.warn("decorateResponse called but response is not an object");
|
|
1086
1201
|
return;
|
|
1087
1202
|
}
|
|
1203
|
+
const extRes = res;
|
|
1088
1204
|
try {
|
|
1089
1205
|
//
|
|
1090
1206
|
//
|
|
1091
1207
|
// Decorate Headers
|
|
1092
1208
|
//
|
|
1093
1209
|
// X-Powered-By, override "Express" but nothing else
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1210
|
+
const currentPoweredBy = safeGetHeader(extRes, kit.HTTP.HEADER.POWERED_BY);
|
|
1211
|
+
if (!currentPoweredBy || currentPoweredBy === "Express") {
|
|
1212
|
+
safeSetHeader(extRes, kit.HTTP.HEADER.POWERED_BY, kit.JAYPIE.LIB.EXPRESS);
|
|
1097
1213
|
}
|
|
1098
1214
|
// X-Project-Environment
|
|
1099
1215
|
if (process.env.PROJECT_ENV) {
|
|
1100
|
-
|
|
1216
|
+
safeSetHeader(extRes, kit.HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);
|
|
1101
1217
|
}
|
|
1102
1218
|
// X-Project-Handler
|
|
1103
1219
|
if (handler) {
|
|
1104
|
-
|
|
1220
|
+
safeSetHeader(extRes, kit.HTTP.HEADER.PROJECT.HANDLER, handler);
|
|
1105
1221
|
}
|
|
1106
1222
|
// X-Project-Invocation
|
|
1107
1223
|
const currentInvoke = getCurrentInvokeUuid();
|
|
1108
1224
|
if (currentInvoke) {
|
|
1109
|
-
|
|
1225
|
+
safeSetHeader(extRes, kit.HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);
|
|
1110
1226
|
}
|
|
1111
1227
|
// X-Project-Key
|
|
1112
1228
|
if (process.env.PROJECT_KEY) {
|
|
1113
|
-
|
|
1229
|
+
safeSetHeader(extRes, kit.HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);
|
|
1114
1230
|
}
|
|
1115
1231
|
// X-Project-Version
|
|
1116
1232
|
if (version) {
|
|
1117
|
-
|
|
1233
|
+
safeSetHeader(extRes, kit.HTTP.HEADER.PROJECT.VERSION, version);
|
|
1118
1234
|
}
|
|
1119
1235
|
//
|
|
1120
1236
|
//
|