feat(logging): enhance HTTP request logging with additional payload details

- Introduced new fields in the HttpPageFetchLog model to capture request and response headers, bodies, and method for improved logging granularity.
- Updated the logging service to serialize and store these new details during HTTP fetch operations, enhancing traceability and debugging capabilities.
- Modified the clickTtHttpPageRoutes to include the new logging features, allowing for optional payload inclusion in log queries.
This commit is contained in:
Torsten Schulz (local)
2026-03-10 22:26:37 +01:00
parent 4f3a1829ca
commit 0e4d1707fd
6 changed files with 143 additions and 23 deletions

View File

@@ -40,6 +40,22 @@ function getOrCreateSid(req) {
return req.query.sid || crypto.randomBytes(16).toString('hex');
}
function serializeFormBody(req) {
if (typeof req.rawBody === 'string' && req.rawBody.length > 0) {
return req.rawBody;
}
if (typeof req.body === 'string') {
return req.body;
}
if (req.body && typeof req.body === 'object' && Object.keys(req.body).length > 0) {
return new URLSearchParams(req.body).toString();
}
return null;
}
/** Domains, deren Links durch den Proxy umgeleitet werden (für Folge-Logs) */
const PROXY_DOMAINS = ['click-tt.de', 'httv.de'];
@@ -264,9 +280,7 @@ router.post('/proxy', async (req, res, next) => {
}
const contentType = req.get('content-type') || 'application/x-www-form-urlencoded';
const body = typeof req.body === 'string' ? req.body : (req.body && Object.keys(req.body).length
? new URLSearchParams(req.body).toString()
: null);
const body = serializeFormBody(req);
const result = await clickTtHttpPageService.fetchWithLogging({
url: targetUrl,
@@ -487,37 +501,52 @@ router.get('/logs', authenticate, async (req, res, next) => {
try {
const limit = Math.min(parseInt(req.query.limit, 10) || 50, 200);
const { fetchType, association, success } = req.query;
const includePayloads = req.query.includePayloads === 'true';
const where = {};
if (fetchType) where.fetchType = fetchType;
if (association) where.association = association;
if (success !== undefined) where.success = success === 'true';
const attributes = [
'id',
'fetchType',
'baseDomain',
'fullUrl',
'association',
'championship',
'clubIdParam',
'requestMethod',
'httpStatus',
'success',
'responseSnippet',
'contentType',
'responseUrl',
'errorMessage',
'executionTimeMs',
'createdAt',
];
if (includePayloads) {
attributes.push(
'requestHeaders',
'requestBody',
'responseHeaders',
'responseBody',
);
}
const logs = await HttpPageFetchLog.findAll({
where: Object.keys(where).length > 0 ? where : undefined,
order: [['createdAt', 'DESC']],
limit,
attributes: [
'id',
'fetchType',
'baseDomain',
'fullUrl',
'association',
'championship',
'clubIdParam',
'httpStatus',
'success',
'responseSnippet',
'contentType',
'errorMessage',
'executionTimeMs',
'createdAt',
],
attributes,
});
res.json({
success: true,
count: logs.length,
includePayloads,
logs,
});
} catch (error) {