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ách và hiể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ăng | Lợi ích |
---|---|
Kiểm tra dữ liệu sớm | Giảm lỗi logic và rủi ro bảo mật. |
Thông báo lỗi rõ ràng | Giúp frontend dễ xử lý và debug. |
Xử lý lỗi tập trung | Không cần try/catch khắp nơi. |
Dễ mở rộng | Có thể thêm custom filter cho từng module. |
⚠️ Lỗi thường gặp và cách khắc phục
Lỗi | Nguyên nhân | Giải pháp |
---|---|---|
Không validate được dữ liệu | Quên import ValidationPipe | Thêm app.useGlobalPipes(new ValidationPipe()) |
Lỗi 500 khi throw exception | Không bắt bằng @Catch() | Đảm bảo filter có decorator @Catch() |
Lỗi không hiển thị message tùy chỉnh | Sai format HttpException | Sử 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.