banatie-service/src/middleware/errorHandler.ts

121 lines
3.1 KiB
TypeScript

import { Request, Response, NextFunction } from "express";
import { GenerateImageResponse } from "../types/api";
/**
* Global error handler for the Express application
*/
export const errorHandler = (
error: Error,
req: Request,
res: Response,
next: NextFunction,
) => {
const timestamp = new Date().toISOString();
const requestId = req.requestId || "unknown";
// Log the error
console.error(`[${timestamp}] [${requestId}] ERROR:`, {
message: error.message,
stack: error.stack,
path: req.path,
method: req.method,
body: req.body,
query: req.query,
});
// Don't send error response if headers already sent
if (res.headersSent) {
return next(error);
}
// Determine error type and status code
let statusCode = 500;
let errorMessage = "Internal server error";
let errorType = "INTERNAL_ERROR";
if (error.name === "ValidationError") {
statusCode = 400;
errorMessage = error.message;
errorType = "VALIDATION_ERROR";
} else if (
error.message.includes("API key") ||
error.message.includes("authentication")
) {
statusCode = 401;
errorMessage = "Authentication failed";
errorType = "AUTH_ERROR";
} else if (
error.message.includes("not found") ||
error.message.includes("404")
) {
statusCode = 404;
errorMessage = "Resource not found";
errorType = "NOT_FOUND";
} else if (
error.message.includes("timeout") ||
error.message.includes("503")
) {
statusCode = 503;
errorMessage = "Service temporarily unavailable";
errorType = "SERVICE_UNAVAILABLE";
} else if (
error.message.includes("overloaded") ||
error.message.includes("rate limit")
) {
statusCode = 429;
errorMessage = "Service overloaded, please try again later";
errorType = "RATE_LIMITED";
}
// Create error response
const errorResponse: GenerateImageResponse = {
success: false,
message: "Request failed",
error: errorMessage,
};
// Add additional debug info in development
if (process.env["NODE_ENV"] === "development") {
(errorResponse as any).debug = {
originalError: error.message,
errorType,
requestId,
timestamp,
};
}
console.log(
`[${timestamp}] [${requestId}] Sending error response: ${statusCode} - ${errorMessage}`,
);
res.status(statusCode).json(errorResponse);
};
/**
* 404 handler for unmatched routes
*/
export const notFoundHandler = (req: Request, res: Response) => {
const timestamp = new Date().toISOString();
const requestId = req.requestId || "unknown";
console.log(
`[${timestamp}] [${requestId}] 404 - Route not found: ${req.method} ${req.path}`,
);
const notFoundResponse: GenerateImageResponse = {
success: false,
message: "Route not found",
error: `The requested endpoint ${req.method} ${req.path} does not exist`,
};
res.status(404).json(notFoundResponse);
};
/**
* Async error wrapper to catch errors in async route handlers
*/
export const asyncHandler =
(fn: Function) => (req: Request, res: Response, next: NextFunction) => {
Promise.resolve(fn(req, res, next)).catch(next);
};