@jaypie/express 1.2.4-rc6 → 1.2.4-rc8

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/esm/index.js CHANGED
@@ -1124,6 +1124,64 @@ function getCurrentInvokeUuid(req) {
1124
1124
  return getWebAdapterUuid();
1125
1125
  }
1126
1126
 
1127
+ //
1128
+ //
1129
+ // Helpers
1130
+ //
1131
+ /**
1132
+ * Safely get a header value from response.
1133
+ * Handles both Express Response and Lambda adapter responses.
1134
+ * Defensive against dd-trace instrumentation issues.
1135
+ */
1136
+ function safeGetHeader(res, name) {
1137
+ try {
1138
+ // Try direct _headers access first (Lambda adapter, avoids dd-trace)
1139
+ if (res._headers instanceof Map) {
1140
+ const value = res._headers.get(name.toLowerCase());
1141
+ return value ? String(value) : undefined;
1142
+ }
1143
+ // Fall back to getHeader (more standard than get)
1144
+ if (typeof res.getHeader === "function") {
1145
+ const value = res.getHeader(name);
1146
+ return value ? String(value) : undefined;
1147
+ }
1148
+ // Last resort: try get
1149
+ if (typeof res.get === "function") {
1150
+ const value = res.get(name);
1151
+ return value ? String(value) : undefined;
1152
+ }
1153
+ }
1154
+ catch {
1155
+ // Silently fail - caller will handle missing value
1156
+ }
1157
+ return undefined;
1158
+ }
1159
+ /**
1160
+ * Safely set a header value on response.
1161
+ * Handles both Express Response and Lambda adapter responses.
1162
+ * Defensive against dd-trace instrumentation issues.
1163
+ */
1164
+ function safeSetHeader(res, name, value) {
1165
+ try {
1166
+ // Try direct _headers access first (Lambda adapter, avoids dd-trace)
1167
+ if (res._headers instanceof Map) {
1168
+ res._headers.set(name.toLowerCase(), value);
1169
+ return;
1170
+ }
1171
+ // Fall back to setHeader (more standard than set)
1172
+ if (typeof res.setHeader === "function") {
1173
+ res.setHeader(name, value);
1174
+ return;
1175
+ }
1176
+ // Last resort: try set
1177
+ if (typeof res.set === "function") {
1178
+ res.set(name, value);
1179
+ }
1180
+ }
1181
+ catch {
1182
+ // Silently fail - header just won't be set
1183
+ }
1184
+ }
1127
1185
  //
1128
1186
  //
1129
1187
  // Main
@@ -1140,36 +1198,37 @@ const decorateResponse = (res, { handler = "", version = process.env.PROJECT_VER
1140
1198
  log$1.warn("decorateResponse called but response is not an object");
1141
1199
  return;
1142
1200
  }
1201
+ const extRes = res;
1143
1202
  try {
1144
1203
  //
1145
1204
  //
1146
1205
  // Decorate Headers
1147
1206
  //
1148
1207
  // X-Powered-By, override "Express" but nothing else
1149
- if (!res.get(HTTP.HEADER.POWERED_BY) ||
1150
- res.get(HTTP.HEADER.POWERED_BY) === "Express") {
1151
- res.set(HTTP.HEADER.POWERED_BY, JAYPIE.LIB.EXPRESS);
1208
+ const currentPoweredBy = safeGetHeader(extRes, HTTP.HEADER.POWERED_BY);
1209
+ if (!currentPoweredBy || currentPoweredBy === "Express") {
1210
+ safeSetHeader(extRes, HTTP.HEADER.POWERED_BY, JAYPIE.LIB.EXPRESS);
1152
1211
  }
1153
1212
  // X-Project-Environment
1154
1213
  if (process.env.PROJECT_ENV) {
1155
- res.set(HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);
1214
+ safeSetHeader(extRes, HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);
1156
1215
  }
1157
1216
  // X-Project-Handler
1158
1217
  if (handler) {
1159
- res.set(HTTP.HEADER.PROJECT.HANDLER, handler);
1218
+ safeSetHeader(extRes, HTTP.HEADER.PROJECT.HANDLER, handler);
1160
1219
  }
1161
1220
  // X-Project-Invocation
1162
1221
  const currentInvoke = getCurrentInvokeUuid();
1163
1222
  if (currentInvoke) {
1164
- res.set(HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);
1223
+ safeSetHeader(extRes, HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);
1165
1224
  }
1166
1225
  // X-Project-Key
1167
1226
  if (process.env.PROJECT_KEY) {
1168
- res.set(HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);
1227
+ safeSetHeader(extRes, HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);
1169
1228
  }
1170
1229
  // X-Project-Version
1171
1230
  if (version) {
1172
- res.set(HTTP.HEADER.PROJECT.VERSION, version);
1231
+ safeSetHeader(extRes, HTTP.HEADER.PROJECT.VERSION, version);
1173
1232
  }
1174
1233
  //
1175
1234
  //
@@ -1229,6 +1288,55 @@ function summarizeResponse(res, extras) {
1229
1288
 
1230
1289
  // Cast logger to extended interface for runtime features not in type definitions
1231
1290
  const logger$1 = log;
1291
+ //
1292
+ //
1293
+ // Helpers - Safe response methods to bypass dd-trace interception
1294
+ //
1295
+ /**
1296
+ * Check if response is a Lambda mock response with direct _headers access.
1297
+ */
1298
+ function isLambdaMockResponse(res) {
1299
+ return res._headers instanceof Map;
1300
+ }
1301
+ /**
1302
+ * Safely send a JSON response, avoiding dd-trace interception.
1303
+ * For Lambda mock responses, directly sets headers and writes to stream.
1304
+ */
1305
+ function safeSendJson(res, statusCode, data) {
1306
+ if (isLambdaMockResponse(res)) {
1307
+ // Direct access for Lambda mock responses - bypasses dd-trace
1308
+ res._headers.set("content-type", "application/json");
1309
+ res.statusCode = statusCode;
1310
+ res.end(JSON.stringify(data));
1311
+ return;
1312
+ }
1313
+ // Fall back to standard Express methods for real responses
1314
+ res.status(statusCode).json(data);
1315
+ }
1316
+ /**
1317
+ * Safely send a response body, avoiding dd-trace interception.
1318
+ * For Lambda mock responses, directly writes to stream.
1319
+ */
1320
+ function safeSend(res, statusCode, body) {
1321
+ if (isLambdaMockResponse(res)) {
1322
+ // Direct access for Lambda mock responses - bypasses dd-trace
1323
+ res.statusCode = statusCode;
1324
+ if (body !== undefined) {
1325
+ res.end(body);
1326
+ }
1327
+ else {
1328
+ res.end();
1329
+ }
1330
+ return;
1331
+ }
1332
+ // Fall back to standard Express methods for real responses
1333
+ if (body !== undefined) {
1334
+ res.status(statusCode).send(body);
1335
+ }
1336
+ else {
1337
+ res.status(statusCode).send();
1338
+ }
1339
+ }
1232
1340
  function expressHandler(handlerOrOptions, optionsOrHandler) {
1233
1341
  /* eslint-enable no-redeclare */
1234
1342
  let handler;
@@ -1445,30 +1553,30 @@ function expressHandler(handlerOrOptions, optionsOrHandler) {
1445
1553
  if (typeof response === "object") {
1446
1554
  if (typeof response.json ===
1447
1555
  "function") {
1448
- res.json(response.json());
1556
+ safeSendJson(res, status, response.json());
1449
1557
  }
1450
1558
  else {
1451
- res.status(status).json(response);
1559
+ safeSendJson(res, status, response);
1452
1560
  }
1453
1561
  }
1454
1562
  else if (typeof response === "string") {
1455
1563
  try {
1456
- res.status(status).json(JSON.parse(response));
1564
+ safeSendJson(res, status, JSON.parse(response));
1457
1565
  }
1458
1566
  catch {
1459
- res.status(status).send(response);
1567
+ safeSend(res, status, response);
1460
1568
  }
1461
1569
  }
1462
1570
  else if (response === true) {
1463
- res.status(HTTP.CODE.CREATED).send();
1571
+ safeSend(res, HTTP.CODE.CREATED);
1464
1572
  }
1465
1573
  else {
1466
- res.status(status).send(response);
1574
+ safeSend(res, status, response);
1467
1575
  }
1468
1576
  }
1469
1577
  else {
1470
1578
  // No response
1471
- res.status(HTTP.CODE.NO_CONTENT).send();
1579
+ safeSend(res, HTTP.CODE.NO_CONTENT);
1472
1580
  }
1473
1581
  }
1474
1582
  else {