import { Response, NextFunction } from 'express'; import { ApiKeyRequest } from './apiKey'; import { mainPool } from '../config/database'; interface LogData { endpoint_id: string | null; api_key_id: string | null; method: string; path: string; request_params: any; request_body: any; response_status: number; response_data: any; execution_time: number; error_message: string | null; ip_address: string; user_agent: string; } export const createLoggingMiddleware = (endpointId: string, shouldLog: boolean) => { return async (req: ApiKeyRequest, res: Response, next: NextFunction) => { if (!shouldLog) { return next(); } const startTime = Date.now(); // Capture original methods const originalJson = res.json.bind(res); const originalSend = res.send.bind(res); let responseData: any = null; let isLogged = false; const logRequest = async (data: any, status: number, errorMsg: string | null = null) => { if (isLogged) return; // Prevent duplicate logging isLogged = true; const executionTime = Date.now() - startTime; const logData: LogData = { endpoint_id: endpointId, api_key_id: req.apiKey?.id || null, method: req.method, path: req.path, request_params: req.query || {}, request_body: req.body || {}, response_status: status, response_data: data, execution_time: executionTime, error_message: errorMsg, ip_address: req.ip || req.socket.remoteAddress || 'unknown', user_agent: req.headers['user-agent'] || 'unknown', }; try { await mainPool.query( `INSERT INTO request_logs ( endpoint_id, api_key_id, method, path, request_params, request_body, response_status, response_data, execution_time, error_message, ip_address, user_agent ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)`, [ logData.endpoint_id, logData.api_key_id, logData.method, logData.path, JSON.stringify(logData.request_params), JSON.stringify(logData.request_body), logData.response_status, JSON.stringify(logData.response_data), logData.execution_time, logData.error_message, logData.ip_address, logData.user_agent, ] ); } catch (error) { console.error('Failed to log request:', error); } }; // Override res.json res.json = function (data: any) { responseData = data; logRequest(data, res.statusCode); return originalJson(data); }; // Override res.send res.send = function (data: any) { responseData = data; logRequest(data, res.statusCode); return originalSend(data); }; // Handle errors res.on('finish', () => { if (!isLogged && responseData === null) { logRequest(null, res.statusCode); } }); next(); }; };