@mastra/express 1.1.7 → 1.1.8-alpha.0
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/CHANGELOG.md +39 -0
- package/LICENSE.md +15 -0
- package/dist/index.cjs +121 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +121 -125
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/dist/auth-middleware.d.ts +0 -4
- package/dist/auth-middleware.d.ts.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @mastra/express
|
|
2
2
|
|
|
3
|
+
## 1.1.8-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added RBAC permission enforcement to all server adapters. When an auth provider is configured, each route's required permission is checked against the authenticated user's permissions before the handler runs. Permissions are derived automatically from route paths and HTTP methods using the convention-based system from `@mastra/server`. ([#13163](https://github.com/mastra-ai/mastra/pull/13163))
|
|
8
|
+
|
|
9
|
+
- Added HTTP request logging middleware. Enable with `apiReqLogs: true` for default settings, or pass a configuration object for fine-grained control. ([#11907](https://github.com/mastra-ai/mastra/pull/11907))
|
|
10
|
+
|
|
11
|
+
**Simple activation**
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
const mastra = new Mastra({
|
|
15
|
+
server: { build: { apiReqLogs: true } },
|
|
16
|
+
});
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Advanced configuration**
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
const mastra = new Mastra({
|
|
23
|
+
server: {
|
|
24
|
+
build: {
|
|
25
|
+
apiReqLogs: {
|
|
26
|
+
enabled: true,
|
|
27
|
+
level: 'debug',
|
|
28
|
+
excludePaths: ['/health'],
|
|
29
|
+
includeHeaders: true,
|
|
30
|
+
includeQueryParams: true,
|
|
31
|
+
redactHeaders: ['authorization', 'cookie'],
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- Updated dependencies [[`504fc8b`](https://github.com/mastra-ai/mastra/commit/504fc8b9d0ddab717577ad3bf9c95ea4bd5377bd), [`f9c150b`](https://github.com/mastra-ai/mastra/commit/f9c150b7595ad05ad9cc9a11098e2944361e8c22), [`88de7e8`](https://github.com/mastra-ai/mastra/commit/88de7e8dfe4b7e1951a9e441bb33136e705ce24e), [`6dbeeb9`](https://github.com/mastra-ai/mastra/commit/6dbeeb94a8b1eebb727300d1a98961f882180794), [`edee4b3`](https://github.com/mastra-ai/mastra/commit/edee4b37dff0af515fc7cc0e8d71ee39e6a762f0), [`3790c75`](https://github.com/mastra-ai/mastra/commit/3790c7578cc6a47d854eb12d89e6b1912867fe29), [`e7a235b`](https://github.com/mastra-ai/mastra/commit/e7a235be6472e0c870ed6c791ddb17c492dc188b), [`d51d298`](https://github.com/mastra-ai/mastra/commit/d51d298953967aab1f58ec965b644d109214f085), [`6dbeeb9`](https://github.com/mastra-ai/mastra/commit/6dbeeb94a8b1eebb727300d1a98961f882180794), [`d5f0d8d`](https://github.com/mastra-ai/mastra/commit/d5f0d8d6a03e515ddaa9b5da19b7e44b8357b07b), [`09c3b18`](https://github.com/mastra-ai/mastra/commit/09c3b1802ff14e243a8a8baea327440bc8cc2e32), [`b896379`](https://github.com/mastra-ai/mastra/commit/b8963791c6afa79484645fcec596a201f936b9a2), [`85c84eb`](https://github.com/mastra-ai/mastra/commit/85c84ebb78aebfcba9d209c8e152b16d7a00cb71), [`a89272a`](https://github.com/mastra-ai/mastra/commit/a89272a5d71939b9fcd284e6a6dc1dd091a6bdcf), [`ee9c8df`](https://github.com/mastra-ai/mastra/commit/ee9c8df644f19d055af5f496bf4942705f5a47b7), [`77b4a25`](https://github.com/mastra-ai/mastra/commit/77b4a254e51907f8ff3a3ba95596a18e93ae4b35), [`276246e`](https://github.com/mastra-ai/mastra/commit/276246e0b9066a1ea48bbc70df84dbe528daaf99), [`08ecfdb`](https://github.com/mastra-ai/mastra/commit/08ecfdbdad6fb8285deef86a034bdf4a6047cfca), [`d5f628c`](https://github.com/mastra-ai/mastra/commit/d5f628ca86c6f6f3ff1035d52f635df32dd81cab), [`524c0f3`](https://github.com/mastra-ai/mastra/commit/524c0f3c434c3d9d18f66338dcef383d6161b59c), [`c18a0e9`](https://github.com/mastra-ai/mastra/commit/c18a0e9cef1e4ca004b2963d35e4cfc031971eac), [`4bd21ea`](https://github.com/mastra-ai/mastra/commit/4bd21ea43d44d0a0427414fc047577f9f0aa3bec), [`115a7a4`](https://github.com/mastra-ai/mastra/commit/115a7a47db5e9896fec12ae6507501adb9ec89bf), [`22a48ae`](https://github.com/mastra-ai/mastra/commit/22a48ae2513eb54d8d79dad361fddbca97a155e8), [`3c6ef79`](https://github.com/mastra-ai/mastra/commit/3c6ef798481e00d6d22563be2de98818fd4dd5e0), [`9311c17`](https://github.com/mastra-ai/mastra/commit/9311c17d7a0640d9c4da2e71b814dc67c57c6369), [`7edf78f`](https://github.com/mastra-ai/mastra/commit/7edf78f80422c43e84585f08ba11df0d4d0b73c5), [`1c4221c`](https://github.com/mastra-ai/mastra/commit/1c4221cf6032ec98d0e094d4ee11da3e48490d96), [`6dbeeb9`](https://github.com/mastra-ai/mastra/commit/6dbeeb94a8b1eebb727300d1a98961f882180794), [`d25b9ea`](https://github.com/mastra-ai/mastra/commit/d25b9eabd400167255a97b690ffbc4ee4097ded5), [`fe1ce5c`](https://github.com/mastra-ai/mastra/commit/fe1ce5c9211c03d561606fda95cbfe7df1d9a9b5), [`b03c0e0`](https://github.com/mastra-ai/mastra/commit/b03c0e0389a799523929a458b0509c9e4244d562), [`0a8366b`](https://github.com/mastra-ai/mastra/commit/0a8366b0a692fcdde56c4d526e4cf03c502ae4ac), [`85664e9`](https://github.com/mastra-ai/mastra/commit/85664e9fd857320fbc245e301f764f45f66f32a3), [`bc79650`](https://github.com/mastra-ai/mastra/commit/bc796500c6e0334faa158a96077e3fb332274869), [`9257d01`](https://github.com/mastra-ai/mastra/commit/9257d01d1366d81f84c582fe02b5e200cf9621f4), [`3a3a59e`](https://github.com/mastra-ai/mastra/commit/3a3a59e8ffaa6a985fe3d9a126a3f5ade11a6724), [`3108d4e`](https://github.com/mastra-ai/mastra/commit/3108d4e649c9fddbf03253a6feeb388a5fa9fa5a), [`0c33b2c`](https://github.com/mastra-ai/mastra/commit/0c33b2c9db537f815e1c59e2c898ffce2e395a79), [`191e5bd`](https://github.com/mastra-ai/mastra/commit/191e5bd29b82f5bda35243945790da7bc7b695c2), [`f77cd94`](https://github.com/mastra-ai/mastra/commit/f77cd94c44eabed490384e7d19232a865e13214c), [`e8135c7`](https://github.com/mastra-ai/mastra/commit/e8135c7e300dac5040670eec7eab896ac6092e30), [`daca48f`](https://github.com/mastra-ai/mastra/commit/daca48f0fb17b7ae0b62a2ac40cf0e491b2fd0b7), [`bc79650`](https://github.com/mastra-ai/mastra/commit/bc796500c6e0334faa158a96077e3fb332274869), [`257d14f`](https://github.com/mastra-ai/mastra/commit/257d14faca5931f2e4186fc165b6f0b1f915deee), [`352f25d`](https://github.com/mastra-ai/mastra/commit/352f25da316b24cdd5b410fd8dddf6a8b763da2a), [`93477d0`](https://github.com/mastra-ai/mastra/commit/93477d0769b8a13ea5ed73d508d967fb23eaeed9), [`31c78b3`](https://github.com/mastra-ai/mastra/commit/31c78b3eb28f58a8017f1dcc795c33214d87feac), [`0bc0720`](https://github.com/mastra-ai/mastra/commit/0bc07201095791858087cc56f353fcd65e87ab54), [`36516ac`](https://github.com/mastra-ai/mastra/commit/36516aca1021cbeb42e74751b46a2614101f37c8), [`e947652`](https://github.com/mastra-ai/mastra/commit/e9476527fdecb4449e54570e80dfaf8466901254), [`3c6ef79`](https://github.com/mastra-ai/mastra/commit/3c6ef798481e00d6d22563be2de98818fd4dd5e0), [`9257d01`](https://github.com/mastra-ai/mastra/commit/9257d01d1366d81f84c582fe02b5e200cf9621f4), [`ec248f6`](https://github.com/mastra-ai/mastra/commit/ec248f6b56e8a037c066c49b2178e2507471d988)]:
|
|
39
|
+
- @mastra/core@1.9.0-alpha.0
|
|
40
|
+
- @mastra/server@1.9.0-alpha.0
|
|
41
|
+
|
|
3
42
|
## 1.1.7
|
|
4
43
|
|
|
5
44
|
### Patch Changes
|
package/LICENSE.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
Portions of this software are licensed as follows:
|
|
2
|
+
|
|
3
|
+
- All content that resides under any directory named "ee/" within this
|
|
4
|
+
repository, including but not limited to:
|
|
5
|
+
- `packages/core/src/auth/ee/`
|
|
6
|
+
- `packages/server/src/server/auth/ee/`
|
|
7
|
+
is licensed under the license defined in `ee/LICENSE`.
|
|
8
|
+
|
|
9
|
+
- All third-party components incorporated into the Mastra Software are
|
|
10
|
+
licensed under the original license provided by the owner of the
|
|
11
|
+
applicable component.
|
|
12
|
+
|
|
13
|
+
- Content outside of the above-mentioned directories or restrictions is
|
|
14
|
+
available under the "Apache License 2.0" as defined below.
|
|
15
|
+
|
|
1
16
|
# Apache License 2.0
|
|
2
17
|
|
|
3
18
|
Copyright (c) 2025 Kepler Software, Inc.
|
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var busboy = require('@fastify/busboy');
|
|
4
|
+
var auth = require('@mastra/server/auth');
|
|
4
5
|
var error = require('@mastra/server/handlers/error');
|
|
5
6
|
var serverAdapter = require('@mastra/server/server-adapter');
|
|
6
|
-
var auth = require('@mastra/server/auth');
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
9
|
|
|
@@ -213,130 +213,39 @@ ZodError.create = (issues) => {
|
|
|
213
213
|
const error = new ZodError(issues);
|
|
214
214
|
return error;
|
|
215
215
|
};
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (!
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
if (auth.isDevPlaygroundRequest(path, method, getHeader, authConfig, customRouteAuthConfig)) {
|
|
227
|
-
return next();
|
|
228
|
-
}
|
|
229
|
-
if (!auth.isProtectedPath(req.path, req.method, authConfig, customRouteAuthConfig)) {
|
|
230
|
-
return next();
|
|
231
|
-
}
|
|
232
|
-
if (auth.canAccessPublicly(req.path, req.method, authConfig)) {
|
|
233
|
-
return next();
|
|
234
|
-
}
|
|
235
|
-
const authHeader = req.headers.authorization;
|
|
236
|
-
let token = authHeader ? authHeader.replace("Bearer ", "") : null;
|
|
237
|
-
if (!token && req.query.apiKey) {
|
|
238
|
-
token = req.query.apiKey || null;
|
|
239
|
-
}
|
|
240
|
-
if (!token) {
|
|
241
|
-
return res.status(401).json({ error: "Authentication required" });
|
|
242
|
-
}
|
|
243
|
-
try {
|
|
244
|
-
let user;
|
|
245
|
-
if (typeof authConfig.authenticateToken === "function") {
|
|
246
|
-
user = await authConfig.authenticateToken(token, req);
|
|
247
|
-
} else {
|
|
248
|
-
throw new Error("No token verification method configured");
|
|
249
|
-
}
|
|
250
|
-
if (!user) {
|
|
251
|
-
return res.status(401).json({ error: "Invalid or expired token" });
|
|
252
|
-
}
|
|
253
|
-
res.locals.requestContext.set("user", user);
|
|
254
|
-
return next();
|
|
255
|
-
} catch (err) {
|
|
256
|
-
mastra.getLogger()?.error("Authentication error", {
|
|
257
|
-
error: err instanceof Error ? { message: err.message, stack: err.stack } : err
|
|
216
|
+
|
|
217
|
+
// src/index.ts
|
|
218
|
+
var _hasPermissionPromise;
|
|
219
|
+
function loadHasPermission() {
|
|
220
|
+
if (!_hasPermissionPromise) {
|
|
221
|
+
_hasPermissionPromise = import('@mastra/core/auth/ee').then((m) => m.hasPermission).catch(() => {
|
|
222
|
+
console.error(
|
|
223
|
+
"[@mastra/express] Auth features require @mastra/core >= 1.6.0. Please upgrade: npm install @mastra/core@latest"
|
|
224
|
+
);
|
|
225
|
+
return void 0;
|
|
258
226
|
});
|
|
259
|
-
return res.status(401).json({ error: "Invalid or expired token" });
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
var authorizationMiddleware = async (req, res, next) => {
|
|
263
|
-
const mastra = res.locals.mastra;
|
|
264
|
-
const authConfig = mastra.getServer()?.auth;
|
|
265
|
-
const customRouteAuthConfig = res.locals.customRouteAuthConfig;
|
|
266
|
-
if (!authConfig) {
|
|
267
|
-
return next();
|
|
268
|
-
}
|
|
269
|
-
const path = req.path;
|
|
270
|
-
const method = req.method;
|
|
271
|
-
const getHeader = (name) => req.headers[name.toLowerCase()];
|
|
272
|
-
if (auth.isDevPlaygroundRequest(path, method, getHeader, authConfig, customRouteAuthConfig)) {
|
|
273
|
-
return next();
|
|
274
227
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
return res.status(403).json({ error: "Access denied" });
|
|
289
|
-
} catch (err) {
|
|
290
|
-
mastra.getLogger()?.error("Authorization error in authorizeUser", {
|
|
291
|
-
error: err instanceof Error ? { message: err.message, stack: err.stack } : err
|
|
292
|
-
});
|
|
293
|
-
return res.status(500).json({ error: "Authorization error" });
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
if ("authorize" in authConfig && typeof authConfig.authorize === "function") {
|
|
297
|
-
try {
|
|
298
|
-
const context = {
|
|
299
|
-
get: (key) => {
|
|
300
|
-
if (key === "mastra") return res.locals.mastra;
|
|
301
|
-
if (key === "requestContext") return res.locals.requestContext;
|
|
302
|
-
if (key === "registeredTools") return res.locals.registeredTools;
|
|
303
|
-
if (key === "taskStore") return res.locals.taskStore;
|
|
304
|
-
if (key === "customRouteAuthConfig") return res.locals.customRouteAuthConfig;
|
|
305
|
-
return void 0;
|
|
306
|
-
},
|
|
307
|
-
req
|
|
308
|
-
};
|
|
309
|
-
const isAuthorized = await authConfig.authorize(path, method, user, context);
|
|
310
|
-
if (isAuthorized) {
|
|
311
|
-
return next();
|
|
228
|
+
return _hasPermissionPromise;
|
|
229
|
+
}
|
|
230
|
+
function toWebRequest(req) {
|
|
231
|
+
const protocol = req.protocol || "http";
|
|
232
|
+
const host = req.get("host") || "localhost";
|
|
233
|
+
const url = `${protocol}://${host}${req.originalUrl || req.url}`;
|
|
234
|
+
const headers = new Headers();
|
|
235
|
+
for (const [key, value] of Object.entries(req.headers)) {
|
|
236
|
+
if (value) {
|
|
237
|
+
if (Array.isArray(value)) {
|
|
238
|
+
value.forEach((v) => headers.append(key, v));
|
|
239
|
+
} else {
|
|
240
|
+
headers.set(key, value);
|
|
312
241
|
}
|
|
313
|
-
return res.status(403).json({ error: "Access denied" });
|
|
314
|
-
} catch (err) {
|
|
315
|
-
mastra.getLogger()?.error("Authorization error in authorize", {
|
|
316
|
-
error: err instanceof Error ? { message: err.message, stack: err.stack } : err,
|
|
317
|
-
path,
|
|
318
|
-
method
|
|
319
|
-
});
|
|
320
|
-
return res.status(500).json({ error: "Authorization error" });
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if ("rules" in authConfig && authConfig.rules && authConfig.rules.length > 0) {
|
|
324
|
-
const isAuthorized = await auth.checkRules(authConfig.rules, path, method, user);
|
|
325
|
-
if (isAuthorized) {
|
|
326
|
-
return next();
|
|
327
242
|
}
|
|
328
|
-
return res.status(403).json({ error: "Access denied" });
|
|
329
243
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
return res.status(403).json({ error: "Access denied" });
|
|
337
|
-
};
|
|
338
|
-
|
|
339
|
-
// src/index.ts
|
|
244
|
+
return new globalThis.Request(url, {
|
|
245
|
+
method: req.method,
|
|
246
|
+
headers
|
|
247
|
+
});
|
|
248
|
+
}
|
|
340
249
|
var MastraServer = class extends serverAdapter.MastraServer {
|
|
341
250
|
createContextMiddleware() {
|
|
342
251
|
return async (req, res, next) => {
|
|
@@ -599,7 +508,9 @@ var MastraServer = class extends serverAdapter.MastraServer {
|
|
|
599
508
|
method: String(req.method || "GET"),
|
|
600
509
|
getHeader: (name) => req.headers[name.toLowerCase()],
|
|
601
510
|
getQuery: (name) => req.query[name],
|
|
602
|
-
requestContext: res.locals.requestContext
|
|
511
|
+
requestContext: res.locals.requestContext,
|
|
512
|
+
request: toWebRequest(req),
|
|
513
|
+
buildAuthorizeContext: () => toWebRequest(req)
|
|
603
514
|
});
|
|
604
515
|
if (authError) {
|
|
605
516
|
return res.status(authError.status).json({ error: authError.error });
|
|
@@ -670,6 +581,20 @@ var MastraServer = class extends serverAdapter.MastraServer {
|
|
|
670
581
|
abortSignal: res.locals.abortSignal,
|
|
671
582
|
routePrefix: prefix
|
|
672
583
|
};
|
|
584
|
+
const authConfig = this.mastra.getServer()?.auth;
|
|
585
|
+
if (authConfig) {
|
|
586
|
+
const hasPermission = await loadHasPermission();
|
|
587
|
+
if (hasPermission) {
|
|
588
|
+
const userPermissions = res.locals.requestContext.get("userPermissions");
|
|
589
|
+
const permissionError = this.checkRoutePermission(route, userPermissions, hasPermission);
|
|
590
|
+
if (permissionError) {
|
|
591
|
+
return res.status(permissionError.status).json({
|
|
592
|
+
error: permissionError.error,
|
|
593
|
+
message: permissionError.message
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
673
598
|
try {
|
|
674
599
|
const result = await route.handler(handlerParams);
|
|
675
600
|
await this.sendResponse(route, res, result, req, prefix);
|
|
@@ -695,6 +620,43 @@ var MastraServer = class extends serverAdapter.MastraServer {
|
|
|
695
620
|
async registerCustomApiRoutes() {
|
|
696
621
|
if (!await this.buildCustomRouteHandler()) return;
|
|
697
622
|
this.app.use(async (req, res, next) => {
|
|
623
|
+
const path = String(req.path || "/");
|
|
624
|
+
const method = String(req.method || "GET");
|
|
625
|
+
if (auth.isProtectedCustomRoute(path, method, this.customRouteAuthConfig)) {
|
|
626
|
+
const serverRoute = {
|
|
627
|
+
method,
|
|
628
|
+
path,
|
|
629
|
+
responseType: "json",
|
|
630
|
+
handler: async () => {
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
const authError = await this.checkRouteAuth(serverRoute, {
|
|
634
|
+
path,
|
|
635
|
+
method,
|
|
636
|
+
getHeader: (name) => req.headers[name.toLowerCase()],
|
|
637
|
+
getQuery: (name) => req.query[name],
|
|
638
|
+
requestContext: res.locals.requestContext,
|
|
639
|
+
request: toWebRequest(req),
|
|
640
|
+
buildAuthorizeContext: () => toWebRequest(req)
|
|
641
|
+
});
|
|
642
|
+
if (authError) {
|
|
643
|
+
return res.status(authError.status).json({ error: authError.error });
|
|
644
|
+
}
|
|
645
|
+
const authConfig = this.mastra.getServer()?.auth;
|
|
646
|
+
if (authConfig) {
|
|
647
|
+
const hasPermission = await loadHasPermission();
|
|
648
|
+
if (hasPermission) {
|
|
649
|
+
const userPermissions = res.locals.requestContext.get("userPermissions");
|
|
650
|
+
const permissionError = this.checkRoutePermission(serverRoute, userPermissions, hasPermission);
|
|
651
|
+
if (permissionError) {
|
|
652
|
+
return res.status(permissionError.status).json({
|
|
653
|
+
error: permissionError.error,
|
|
654
|
+
message: permissionError.message
|
|
655
|
+
});
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
698
660
|
const response = await this.handleCustomRouteRequest(
|
|
699
661
|
`${req.protocol}://${req.get("host") || "localhost"}${req.originalUrl}`,
|
|
700
662
|
req.method,
|
|
@@ -710,12 +672,46 @@ var MastraServer = class extends serverAdapter.MastraServer {
|
|
|
710
672
|
this.app.use(this.createContextMiddleware());
|
|
711
673
|
}
|
|
712
674
|
registerAuthMiddleware() {
|
|
713
|
-
|
|
714
|
-
|
|
675
|
+
}
|
|
676
|
+
registerHttpLoggingMiddleware() {
|
|
677
|
+
if (!this.httpLoggingConfig?.enabled) {
|
|
715
678
|
return;
|
|
716
679
|
}
|
|
717
|
-
this.app.use(
|
|
718
|
-
|
|
680
|
+
this.app.use((req, res, next) => {
|
|
681
|
+
if (!this.shouldLogRequest(req.path)) {
|
|
682
|
+
return next();
|
|
683
|
+
}
|
|
684
|
+
const start = Date.now();
|
|
685
|
+
const method = req.method;
|
|
686
|
+
const path = req.path;
|
|
687
|
+
res.on("finish", () => {
|
|
688
|
+
const duration = Date.now() - start;
|
|
689
|
+
const status = res.statusCode;
|
|
690
|
+
const level = this.httpLoggingConfig?.level || "info";
|
|
691
|
+
const logData = {
|
|
692
|
+
method,
|
|
693
|
+
path,
|
|
694
|
+
status,
|
|
695
|
+
duration: `${duration}ms`
|
|
696
|
+
};
|
|
697
|
+
if (this.httpLoggingConfig?.includeQueryParams) {
|
|
698
|
+
logData.query = req.query;
|
|
699
|
+
}
|
|
700
|
+
if (this.httpLoggingConfig?.includeHeaders) {
|
|
701
|
+
const headers = { ...req.headers };
|
|
702
|
+
const redactHeaders = this.httpLoggingConfig.redactHeaders || [];
|
|
703
|
+
redactHeaders.forEach((h) => {
|
|
704
|
+
const key = h.toLowerCase();
|
|
705
|
+
if (headers[key] !== void 0) {
|
|
706
|
+
headers[key] = "[REDACTED]";
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
logData.headers = headers;
|
|
710
|
+
}
|
|
711
|
+
this.logger[level](`${method} ${path} ${status} ${duration}ms`, logData);
|
|
712
|
+
});
|
|
713
|
+
next();
|
|
714
|
+
});
|
|
719
715
|
}
|
|
720
716
|
};
|
|
721
717
|
|