Validation và Exception Filter – Cách xử lý lỗi chuyên nghiệp trong NestJS

3 min read

Giới thiệu

Một API chuyên nghiệp không chỉ cần chạy đúng, mà còn phải xử lý lỗi đúng cáchhiển thị thông tin thân thiện cho người dùng.
Trong NestJS, bạn có thể dễ dàng đạt được điều đó nhờ hai công cụ mạnh mẽ:

  • Validation (xác thực dữ liệu đầu vào)
  • Exception Filter (bộ lọc ngoại lệ)

Cả hai giúp ứng dụng của bạn an toàn, dễ bảo trì và chuyên nghiệp hơn rất nhiều.


🧩 Tại sao cần Validation và Exception Filter?

  • Validation đảm bảo dữ liệu client gửi lên đúng định dạng, tránh lỗi logic hoặc crash hệ thống.
  • Exception Filter giúp kiểm soát lỗi tập trung, không để rải rác try/catch khắp nơi.

Khi hai cơ chế này kết hợp, API của bạn sẽ “vững như thép” – không crash, không lỗi ẩn, và luôn phản hồi chuẩn REST.


🧱 Thiết lập Validation trong NestJS

1️⃣ Cài đặt thư viện

npm install class-validator class-transformer

2️⃣ Kích hoạt ValidationPipe toàn cục

// main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      whitelist: true, // loại bỏ field không hợp lệ
      forbidNonWhitelisted: true, // báo lỗi nếu có field lạ
      transform: true, // tự động chuyển kiểu dữ liệu
    }),
  );
  await app.listen(3000);
}
bootstrap();

3️⃣ Tạo DTO để validate dữ liệu

// create-user.dto.ts
import { IsEmail, IsString, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  @MinLength(6)
  password: string;
}

4️⃣ Áp dụng trong Controller

// user.controller.ts
@Post()
create(@Body() dto: CreateUserDto) {
  return this.userService.create(dto);
}

✅ Khi client gửi dữ liệu sai định dạng, hệ thống sẽ tự động trả lỗi dạng JSON gọn gàng:

{
  "statusCode": 400,
  "message": ["email must be an email", "password must be longer than 6 characters"],
  "error": "Bad Request"
}

🧠 Xử lý lỗi nâng cao với Exception Filter

Khi có lỗi xảy ra, ta không nên để mặc định stack trace lộ ra ngoài.
Thay vào đó, hãy tạo Exception Filter để kiểm soát cách trả lỗi.

1️⃣ Tạo Global Exception Filter

// http-exception.filter.ts
import {
  ExceptionFilter,
  Catch,
  ArgumentsHost,
  HttpException,
  HttpStatus,
} from '@nestjs/common';

@Catch()
export class GlobalExceptionFilter implements ExceptionFilter {
  catch(exception: unknown, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();

    const status =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;

    const message =
      exception instanceof HttpException
        ? exception.getResponse()
        : 'Internal server error';

    response.status(status).json({
      success: false,
      statusCode: status,
      message,
      timestamp: new Date().toISOString(),
    });
  }
}

2️⃣ Đăng ký filter toàn cục

// main.ts
app.useGlobalFilters(new GlobalExceptionFilter());

💡 Custom Exception

Bạn có thể định nghĩa các loại lỗi riêng phù hợp với nghiệp vụ.

export class UserNotFoundException extends HttpException {
  constructor() {
    super('User not found', HttpStatus.NOT_FOUND);
  }
}

Sử dụng:

if (!user) throw new UserNotFoundException();

✅ Ưu điểm khi sử dụng Validation và Exception Filter

Tính năngLợi ích
Kiểm tra dữ liệu sớmGiảm lỗi logic và rủi ro bảo mật.
Thông báo lỗi rõ ràngGiúp frontend dễ xử lý và debug.
Xử lý lỗi tập trungKhông cần try/catch khắp nơi.
Dễ mở rộngCó thể thêm custom filter cho từng module.

⚠️ Lỗi thường gặp và cách khắc phục

LỗiNguyên nhânGiải pháp
Không validate được dữ liệuQuên import ValidationPipeThêm app.useGlobalPipes(new ValidationPipe())
Lỗi 500 khi throw exceptionKhông bắt bằng @Catch()Đảm bảo filter có decorator @Catch()
Lỗi không hiển thị message tùy chỉnhSai format HttpExceptionSử dụng super(message, status) đúng chuẩn

🔗 Tham khảo thêm


🚀 Kết luận

Validation giúp đảm bảo dữ liệu đầu vào luôn đúng chuẩn, còn Exception Filter giúp ứng dụng phản hồi lỗi có tổ chức, dễ hiểu và an toàn.
Hơn nữa, việc áp dụng hai công cụ này giúp đội ngũ dev dễ debug, dễ bảo trì và giữ hệ thống hoạt động ổn định.
Vì vậy, hãy luôn coi xử lý lỗi là một phần quan trọng trong thiết kế API của bạn.

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *