improved exception filter

This commit is contained in:
2026-04-19 16:22:49 +03:30
parent ff2e158081
commit 8ba80f86de
+49 -14
View File
@@ -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<FastifyReply>();
const request = ctx.getRequest<FastifyRequest>();
// Safety check: ensure reply has the status method
if (!reply || typeof reply.status !== 'function') {
return;
}
// const request = ctx.getRequest<FastifyRequest>();
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, any>): 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 'مشکلی پیش آمده است';