@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/esm/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Readable, Writable } from 'node:stream';
|
|
2
|
+
import { ServerResponse } from 'node:http';
|
|
2
3
|
import { CorsError, BadRequestError, UnhandledError, GatewayTimeoutError, UnavailableError, BadGatewayError, InternalError, TeapotError, GoneError, MethodNotAllowedError, NotFoundError, ForbiddenError, UnauthorizedError, NotImplementedError } from '@jaypie/errors';
|
|
3
4
|
import { force, envBoolean, JAYPIE, HTTP, getHeaderFrom, jaypieHandler } from '@jaypie/kit';
|
|
4
5
|
import expressCors from 'cors';
|
|
@@ -159,6 +160,10 @@ function createLambdaRequest(event, context) {
|
|
|
159
160
|
//
|
|
160
161
|
// Constants
|
|
161
162
|
//
|
|
163
|
+
// Get Node's internal kOutHeaders symbol from ServerResponse prototype.
|
|
164
|
+
// This is needed for compatibility with Datadog dd-trace instrumentation,
|
|
165
|
+
// which patches HTTP methods and expects this internal state to exist.
|
|
166
|
+
const kOutHeaders$1 = Object.getOwnPropertySymbols(ServerResponse.prototype).find((s) => s.toString() === "Symbol(kOutHeaders)");
|
|
162
167
|
const BINARY_CONTENT_TYPE_PATTERNS = [
|
|
163
168
|
/^application\/octet-stream$/,
|
|
164
169
|
/^application\/pdf$/,
|
|
@@ -189,6 +194,11 @@ class LambdaResponseBuffered extends Writable {
|
|
|
189
194
|
this._headers = new Map();
|
|
190
195
|
this._headersSent = false;
|
|
191
196
|
this._resolve = null;
|
|
197
|
+
// Initialize Node's internal kOutHeaders for dd-trace compatibility.
|
|
198
|
+
// dd-trace patches HTTP methods and expects this internal state.
|
|
199
|
+
if (kOutHeaders$1) {
|
|
200
|
+
this[kOutHeaders$1] = Object.create(null);
|
|
201
|
+
}
|
|
192
202
|
}
|
|
193
203
|
//
|
|
194
204
|
// Promise-based API for getting final result
|
|
@@ -211,14 +221,31 @@ class LambdaResponseBuffered extends Writable {
|
|
|
211
221
|
// In production, log warning but don't throw to match Express behavior
|
|
212
222
|
return this;
|
|
213
223
|
}
|
|
214
|
-
|
|
224
|
+
const lowerName = name.toLowerCase();
|
|
225
|
+
this._headers.set(lowerName, String(value));
|
|
226
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
227
|
+
// Node stores as { 'header-name': ['Header-Name', value] }
|
|
228
|
+
if (kOutHeaders$1) {
|
|
229
|
+
const outHeaders = this[kOutHeaders$1];
|
|
230
|
+
if (outHeaders) {
|
|
231
|
+
outHeaders[lowerName] = [name, String(value)];
|
|
232
|
+
}
|
|
233
|
+
}
|
|
215
234
|
return this;
|
|
216
235
|
}
|
|
217
236
|
getHeader(name) {
|
|
218
237
|
return this._headers.get(name.toLowerCase());
|
|
219
238
|
}
|
|
220
239
|
removeHeader(name) {
|
|
221
|
-
|
|
240
|
+
const lowerName = name.toLowerCase();
|
|
241
|
+
this._headers.delete(lowerName);
|
|
242
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
243
|
+
if (kOutHeaders$1) {
|
|
244
|
+
const outHeaders = this[kOutHeaders$1];
|
|
245
|
+
if (outHeaders) {
|
|
246
|
+
delete outHeaders[lowerName];
|
|
247
|
+
}
|
|
248
|
+
}
|
|
222
249
|
}
|
|
223
250
|
getHeaders() {
|
|
224
251
|
const headers = {};
|
|
@@ -412,6 +439,14 @@ class LambdaResponseBuffered extends Writable {
|
|
|
412
439
|
}
|
|
413
440
|
}
|
|
414
441
|
|
|
442
|
+
//
|
|
443
|
+
//
|
|
444
|
+
// Constants
|
|
445
|
+
//
|
|
446
|
+
// Get Node's internal kOutHeaders symbol from ServerResponse prototype.
|
|
447
|
+
// This is needed for compatibility with Datadog dd-trace instrumentation,
|
|
448
|
+
// which patches HTTP methods and expects this internal state to exist.
|
|
449
|
+
const kOutHeaders = Object.getOwnPropertySymbols(ServerResponse.prototype).find((s) => s.toString() === "Symbol(kOutHeaders)");
|
|
415
450
|
//
|
|
416
451
|
//
|
|
417
452
|
// LambdaResponseStreaming Class
|
|
@@ -434,6 +469,11 @@ class LambdaResponseStreaming extends Writable {
|
|
|
434
469
|
this._pendingWrites = [];
|
|
435
470
|
this._wrappedStream = null;
|
|
436
471
|
this._responseStream = responseStream;
|
|
472
|
+
// Initialize Node's internal kOutHeaders for dd-trace compatibility.
|
|
473
|
+
// dd-trace patches HTTP methods and expects this internal state.
|
|
474
|
+
if (kOutHeaders) {
|
|
475
|
+
this[kOutHeaders] = Object.create(null);
|
|
476
|
+
}
|
|
437
477
|
}
|
|
438
478
|
//
|
|
439
479
|
// Header management
|
|
@@ -444,7 +484,16 @@ class LambdaResponseStreaming extends Writable {
|
|
|
444
484
|
// Headers cannot be changed after body starts
|
|
445
485
|
return this;
|
|
446
486
|
}
|
|
447
|
-
|
|
487
|
+
const lowerName = name.toLowerCase();
|
|
488
|
+
this._headers.set(lowerName, String(value));
|
|
489
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
490
|
+
// Node stores as { 'header-name': ['Header-Name', value] }
|
|
491
|
+
if (kOutHeaders) {
|
|
492
|
+
const outHeaders = this[kOutHeaders];
|
|
493
|
+
if (outHeaders) {
|
|
494
|
+
outHeaders[lowerName] = [name, String(value)];
|
|
495
|
+
}
|
|
496
|
+
}
|
|
448
497
|
return this;
|
|
449
498
|
}
|
|
450
499
|
getHeader(name) {
|
|
@@ -452,7 +501,15 @@ class LambdaResponseStreaming extends Writable {
|
|
|
452
501
|
}
|
|
453
502
|
removeHeader(name) {
|
|
454
503
|
if (!this._headersSent) {
|
|
455
|
-
|
|
504
|
+
const lowerName = name.toLowerCase();
|
|
505
|
+
this._headers.delete(lowerName);
|
|
506
|
+
// Sync with kOutHeaders for dd-trace compatibility
|
|
507
|
+
if (kOutHeaders) {
|
|
508
|
+
const outHeaders = this[kOutHeaders];
|
|
509
|
+
if (outHeaders) {
|
|
510
|
+
delete outHeaders[lowerName];
|
|
511
|
+
}
|
|
512
|
+
}
|
|
456
513
|
}
|
|
457
514
|
}
|
|
458
515
|
getHeaders() {
|
|
@@ -1067,6 +1124,64 @@ function getCurrentInvokeUuid(req) {
|
|
|
1067
1124
|
return getWebAdapterUuid();
|
|
1068
1125
|
}
|
|
1069
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
|
+
}
|
|
1070
1185
|
//
|
|
1071
1186
|
//
|
|
1072
1187
|
// Main
|
|
@@ -1083,36 +1198,37 @@ const decorateResponse = (res, { handler = "", version = process.env.PROJECT_VER
|
|
|
1083
1198
|
log$1.warn("decorateResponse called but response is not an object");
|
|
1084
1199
|
return;
|
|
1085
1200
|
}
|
|
1201
|
+
const extRes = res;
|
|
1086
1202
|
try {
|
|
1087
1203
|
//
|
|
1088
1204
|
//
|
|
1089
1205
|
// Decorate Headers
|
|
1090
1206
|
//
|
|
1091
1207
|
// X-Powered-By, override "Express" but nothing else
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1208
|
+
const currentPoweredBy = safeGetHeader(extRes, HTTP.HEADER.POWERED_BY);
|
|
1209
|
+
if (!currentPoweredBy || currentPoweredBy === "Express") {
|
|
1210
|
+
safeSetHeader(extRes, HTTP.HEADER.POWERED_BY, JAYPIE.LIB.EXPRESS);
|
|
1095
1211
|
}
|
|
1096
1212
|
// X-Project-Environment
|
|
1097
1213
|
if (process.env.PROJECT_ENV) {
|
|
1098
|
-
|
|
1214
|
+
safeSetHeader(extRes, HTTP.HEADER.PROJECT.ENVIRONMENT, process.env.PROJECT_ENV);
|
|
1099
1215
|
}
|
|
1100
1216
|
// X-Project-Handler
|
|
1101
1217
|
if (handler) {
|
|
1102
|
-
|
|
1218
|
+
safeSetHeader(extRes, HTTP.HEADER.PROJECT.HANDLER, handler);
|
|
1103
1219
|
}
|
|
1104
1220
|
// X-Project-Invocation
|
|
1105
1221
|
const currentInvoke = getCurrentInvokeUuid();
|
|
1106
1222
|
if (currentInvoke) {
|
|
1107
|
-
|
|
1223
|
+
safeSetHeader(extRes, HTTP.HEADER.PROJECT.INVOCATION, currentInvoke);
|
|
1108
1224
|
}
|
|
1109
1225
|
// X-Project-Key
|
|
1110
1226
|
if (process.env.PROJECT_KEY) {
|
|
1111
|
-
|
|
1227
|
+
safeSetHeader(extRes, HTTP.HEADER.PROJECT.KEY, process.env.PROJECT_KEY);
|
|
1112
1228
|
}
|
|
1113
1229
|
// X-Project-Version
|
|
1114
1230
|
if (version) {
|
|
1115
|
-
|
|
1231
|
+
safeSetHeader(extRes, HTTP.HEADER.PROJECT.VERSION, version);
|
|
1116
1232
|
}
|
|
1117
1233
|
//
|
|
1118
1234
|
//
|