From 8ba80f86de3010fb87c0a13507738db7fe64ee99 Mon Sep 17 00:00:00 2001 From: morteza-mortezai Date: Sun, 19 Apr 2026 16:22:49 +0330 Subject: [PATCH] improved exception filter --- src/core/exceptions/http.exceptions.ts | 63 ++++++++++++++++++++------ 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/src/core/exceptions/http.exceptions.ts b/src/core/exceptions/http.exceptions.ts index ce271fc..b44bb69 100755 --- a/src/core/exceptions/http.exceptions.ts +++ b/src/core/exceptions/http.exceptions.ts @@ -1,46 +1,81 @@ -import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from '@nestjs/common'; -import { FastifyReply } from 'fastify'; +import { + ArgumentsHost, + Catch, + ExceptionFilter, + HttpException, + HttpStatus, + Logger, +} from '@nestjs/common'; +import { FastifyReply, FastifyRequest } from 'fastify'; @Catch(HttpException) export class HttpExceptionFilter implements ExceptionFilter { + private readonly logger = new Logger(HttpExceptionFilter.name); + catch(exception: HttpException, host: ArgumentsHost) { - // Handle HTTP/REST context try { const ctx = host.switchToHttp(); const reply = ctx.getResponse(); + const request = ctx.getRequest(); - // Safety check: ensure reply has the status method if (!reply || typeof reply.status !== 'function') { return; } - // const request = ctx.getRequest(); - const status = exception.getStatus() || HttpStatus.INTERNAL_SERVER_ERROR; - + const status = exception.getStatus() ?? HttpStatus.INTERNAL_SERVER_ERROR; const exceptionResponse = exception.getResponse(); const message = this.extractMessage(exceptionResponse); + this.logError(exception, request, status, message); + reply.status(status).send({ statusCode: status, success: false, - error: { - message, - // timestamp: new Date().toISOString(), - // path: request.url, - }, + error: { message }, }); } catch { - // If we can't handle it, let it propagate return; } } + private logError( + exception: HttpException, + request: FastifyRequest, + status: number, + message: string | string[], + ) { + const logContext = { + statusCode: status, + method: request.method, + url: request.url, + ip: request.ip, + message, + }; + + // 5xx errors are server faults → error level with stack trace + if (status >= HttpStatus.INTERNAL_SERVER_ERROR) { + this.logger.error( + `[${request.method}] ${request.url} → ${status}`, + exception.stack, + JSON.stringify(logContext), + ); + // 4xx are client faults → warn level, no stack needed + } else { + this.logger.warn( + `[${request.method}] ${request.url} → ${status}`, + JSON.stringify(logContext), + ); + } + } + private extractMessage(response: string | Record): string | string[] { if (typeof response === 'string') { return [response]; } if (typeof response === 'object' && 'message' in response) { - return Array.isArray(response.message) ? response.message : [response.message]; + return Array.isArray(response.message) + ? response.message + : [response.message]; } return 'مشکلی پیش آمده است';