Overview
Catch and format HTTP exceptions with consistent error responses.
Features
- Structured error response
- Request ID included
- Status-based logging
- Stack trace in dev
Installation
npx hanma add http-exception-filter --framework nest
Code
import {
ExceptionFilter,
Catch,
ArgumentsHost,
HttpException,
HttpStatus,
Logger,
} from "@nestjs/common";
import { Request, Response } from "express";
export interface ErrorResponse {
statusCode: number;
error: string;
message: string | string[];
path: string;
timestamp: string;
requestId?: string;
stack?: string;
}
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
private readonly logger = new Logger(HttpExceptionFilter.name);
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
const exceptionResponse = exception.getResponse();
const errorResponse: ErrorResponse = {
statusCode: status,
error: this.getErrorName(status),
message: this.extractMessage(exceptionResponse),
path: request.url,
timestamp: new Date().toISOString(),
requestId: (request as any).id || request.headers["x-request-id"] as string,
};
// Include stack trace in development
if (process.env.NODE_ENV === "development") {
errorResponse.stack = exception.stack;
}
// Log error
if (status >= 500) {
this.logger.error(
`${request.method} ${request.url} - ${status}`,
exception.stack
);
} else if (status >= 400) {
this.logger.warn(
`${request.method} ${request.url} - ${status}: ${errorResponse.message}`
);
}
response.status(status).json(errorResponse);
}
private extractMessage(response: string | object): string | string[] {
if (typeof response === "string") {
return response;
}
if (typeof response === "object" && response !== null) {
const { message, errors } = response as any;
// Handle validation errors array
if (Array.isArray(errors)) {
return errors;
}
if (Array.isArray(message)) {
return message;
}
if (typeof message === "string") {
return message;
}
}
return "An error occurred";
}
private getErrorName(status: number): string {
const errorNames: Record<number, string> = {
400: "Bad Request",
401: "Unauthorized",
403: "Forbidden",
404: "Not Found",
405: "Method Not Allowed",
406: "Not Acceptable",
408: "Request Timeout",
409: "Conflict",
410: "Gone",
413: "Payload Too Large",
415: "Unsupported Media Type",
422: "Unprocessable Entity",
429: "Too Many Requests",
500: "Internal Server Error",
501: "Not Implemented",
502: "Bad Gateway",
503: "Service Unavailable",
504: "Gateway Timeout",
};
return errorNames[status] || "Error";
}
}
Usage
// Global usage
app.useGlobalFilters(new HttpExceptionFilter());
Dependencies
No external dependencies required.
Frequently Asked Questions
How do I install HTTP Exception Filter?
Run the following command:
npx hanma add http-exception-filter --framework nestHow do I use this snippet?
Copy the code and paste it into your project. The snippet will be saved to
src/filters/http-exception.filter.ts.Can I customize this snippet?
Yes! All snippets are copy-paste code that you own. Feel free to modify them to fit your needs.
Does this work with other frameworks?
This snippet is designed for the specific framework. Check the other framework pages for equivalent implementations.