UNPKG

powr-sdk-api

Version:

Shared API core library for PowrStack projects. Zero dependencies - works with Express, Next.js API routes, and other frameworks. All features are optional and install only what you need.

156 lines (139 loc) 5 kB
"use strict"; const logger = require("../logger"); const requestHandler = (req, res, next) => { try { // Add request timestamp req.requestTime = new Date().toISOString(); // Add request ID for tracking req.requestId = req.headers['x-request-id'] || Math.random().toString(36).substring(2, 15); // Set default response headers res.setHeader('X-Request-ID', req.requestId); res.setHeader('X-Request-Time', req.requestTime); // Log the incoming request with details const requestDetails = { method: req.method, path: req.path, query: req.query, ip: req.ip, userAgent: req.headers['user-agent'], requestId: req.requestId, timestamp: req.requestTime }; // Log request body if present, redacting sensitive information if (Object.keys(req.body).length > 0) { const logBody = { ...req.body }; if (logBody.password) logBody.password = "[REDACTED]"; if (logBody.token) logBody.token = "[REDACTED]"; requestDetails.body = logBody; } logger.info(`Incoming request: ${req.method} ${req.path}`, requestDetails); // Add error handler to response object if not already present if (!res.error) { res.error = (message, statusCode = 500, error = null) => { // Extract error details for logging and response let errorDetails = null; let userFriendlyMessage = message; if (error) { // If error is an Error object, extract relevant properties if (error instanceof Error) { // For logging, include the stack trace logger.error(message, { statusCode, requestId: req.requestId, error: { message: error.message, stack: error.stack } }); // For response, only include the error message without stack errorDetails = error.message; // If no user-friendly message was provided, use a generic one if (message === error.message || !message || message === '{}') { userFriendlyMessage = 'An error occurred while processing your request'; } } else if (typeof error === 'object') { // Log the full error object logger.error(message, { statusCode, requestId: req.requestId, error }); // For response, use the error message or a stringified version errorDetails = error.message || JSON.stringify(error); // If no user-friendly message was provided, use a generic one if (!message || message === '{}') { userFriendlyMessage = 'An error occurred while processing your request'; } } else { // If error is a primitive, convert to string errorDetails = String(error); logger.error(message, { statusCode, requestId: req.requestId, error: errorDetails }); // If no user-friendly message was provided, use a generic one if (!message || message === '{}') { userFriendlyMessage = 'An error occurred while processing your request'; } } } else { // Log without error details logger.error(message, { statusCode, requestId: req.requestId }); // If no user-friendly message was provided, use a generic one if (!message || message === '{}') { userFriendlyMessage = 'An error occurred while processing your request'; } } // Create response object const response = { success: false, message: userFriendlyMessage, requestId: req.requestId }; // Include error details in response if available if (errorDetails) { response.error = errorDetails; } return res.status(statusCode).json(response); }; } // Add success handler to response object if not already present if (!res.success) { res.success = (message = 'Success', statusCode = 200, data = null) => { logger.info(message, { statusCode, requestId: req.requestId, data }); // Create response object const response = { success: true, message, requestId: req.requestId }; // Add data to response and log if available if (data !== null) { response.data = data; } return res.status(statusCode).json(response); }; } // Continue to the next middleware next(); } catch (error) { logger.error('Error in request handler', { error, requestId: req.requestId }); return res.error('Internal server error', 500, error); } }; module.exports = { requestHandler };