powr-sdk-api
Version:
Shared API core library for PowrStack projects
156 lines (139 loc) • 5 kB
JavaScript
;
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
};