import { Request, Response, NextFunction } from 'express'; import { getLogger } from '../utils/logging.js'; import { BaseError, HttpStatusCode, formatErrorForClient, isOperationalError, ValidationError } from '../utils/error-handling.js'; const logger = getLogger(); /** * Middleware for logging requests (for development debug only) */ export function requestLogger(req: Request, res: Response, next: NextFunction): void { // Only log detailed debug information, not the basic request // This avoids duplicate logs with request-tracking.ts // Log headers in development mode logger.debug('Headers:', req.headers); // Log body for POST/PUT requests if (['POST', 'PUT'].includes(req.method) && req.body) { logger.debug('Body:', req.body); } // Log query parameters if (Object.keys(req.query).length > 0) { logger.debug('Query params:', req.query); } next(); } /** * Middleware for error handling */ export function errorHandler(err: Error | BaseError | unknown, req: Request, res: Response, next: NextFunction): void { const timestamp = new Date().toISOString(); // Determine if error is expected (operational) or unexpected (programming) const isOperational = isOperationalError(err); // Set appropriate HTTP status code const statusCode = err instanceof BaseError ? err.statusCode : HttpStatusCode.INTERNAL_SERVER_ERROR; // Format error for client response const errorResponse = formatErrorForClient(err); // Add request information const requestInfo = { method: req.method, path: req.path, query: req.query, ip: req.ip, timestamp }; // For operational errors, just log at info level if (isOperational) { logger.info('Operational error handling request:', { error: err, request: requestInfo, response: errorResponse }); } // For programming errors, log at error level with more details else { logger.error('Unexpected error handling request:', { error: err, stack: err instanceof Error ? err.stack : undefined, request: requestInfo, response: errorResponse }); } // Send appropriate response if headers not already sent if (!res.headersSent) { res.status(statusCode).json({ ...errorResponse, timestamp }); } // Forward to default Express error handler next(err); } /** * Middleware for validating session ID */ export function validateSessionId(req: Request, res: Response, next: NextFunction): void { const sessionId = req.query.sessionId as string; if (!sessionId) { logger.warn('No session ID provided in request URL'); const validationError = new ValidationError( 'Missing required session ID parameter', [{ field: 'sessionId', message: 'Session ID is required in query parameters' }] ); return next(validationError); } // Validate format if needed if (!/^[a-zA-Z0-9-]+$/.test(sessionId)) { logger.warn(`Invalid session ID format: ${sessionId}`); const validationError = new ValidationError( 'Invalid session ID format', [{ field: 'sessionId', message: 'Session ID must contain only alphanumeric characters and hyphens' }] ); return next(validationError); } // Attach session ID to request object for later use (req as any).sessionId = sessionId; next(); }