Class 06: Middleware, Interceptor, Guard
NestJS là một framework mạnh mẽ của Node.js hỗ trợ nhiều tính năng của kiến trúc ứng dụng backend hiện đại. Ba thành phần quan trọng trong NestJS để kiểm soát luồng xử lý yêu cầu và bảo mật là: Middleware, Interceptor, và Guard.
Middleware là gì? Ứng dụng trong logging và xác thực
Middleware là gì?
Middleware là một hàm được gọi trước khi request được xử lý bởi bất kỳ route handler nào. Có thể dùng để:
Ghi log các request
Kiểm tra token
Chặn IP
Sửa đổi request
Ví dụ: Tạo middleware ghi log request
// common/middleware/logger.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
}
}
Áp dụng middleware
// app.module.ts
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { LoggerMiddleware } from './common/middleware/logger.middleware';
import { UsersModule } from './users/users.module';
@Module({
imports: [UsersModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(LoggerMiddleware).forRoutes('*');
}
}
Interceptor: response transformation, timeout, logging
Interceptor là gì?
Interceptor là lớp trung gian dùng để can thiệp vào luồng xử lý request và response. Có thể dùng để:
Biến đổi dữ liệu trả về
Thêm timeout cho request
Log thời gian xử lý
Cache
Ví dụ: Interceptor thêm metadata
// common/interceptors/transform.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
} from '@nestjs/common';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
map(data => ({
statusCode: 200,
timestamp: new Date().toISOString(),
data,
})),
);
}
}
Áp dụng interceptor toàn cục
// main.ts
import { TransformInterceptor } from './common/interceptors/transform.interceptor';
app.useGlobalInterceptors(new TransformInterceptor());
Guard: phân quyền, bảo vệ route
Guard là gì?
Guard quyết định có cho phép request đi tiếp hay không, thường dùng cho:
Kiểm tra quyền (role)
Kiểm tra xác thực JWT
Chặn IP
Ví dụ: Guard đơn giản kiểm tra header x-api-key
x-api-key
// common/guards/api-key.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Request } from 'express';
@Injectable()
export class ApiKeyGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request: Request = context.switchToHttp().getRequest();
const apiKey = request.headers['x-api-key'];
return apiKey === '123456'; // kiểm tra khóa đơn giản
}
}
Áp dụng guard cho controller hoặc method
// users/users.controller.ts
import { UseGuards } from '@nestjs/common';
import { ApiKeyGuard } from '../common/guards/api-key.guard';
@UseGuards(ApiKeyGuard)
@Get('protected')
getProtectedData() {
return { message: 'Chỉ truy cập khi có API key đúng' };
}
Thực hành: Tạo Middleware kiểm tra request, Guard chặn IP
Mục tiêu
Middleware kiểm tra nếu header
x-custom-header
không tồn tại thì log cảnh báoGuard chặn truy cập từ IP nằm trong danh sách đen
Bước 1: Middleware kiểm tra header
// common/middleware/check-header.middleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class CheckHeaderMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
if (!req.headers['x-custom-header']) {
console.warn('Thiếu x-custom-header!');
}
next();
}
}
Bước 2: Guard chặn IP
// common/guards/ip-block.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Request } from 'express';
@Injectable()
export class IPBlockGuard implements CanActivate {
private readonly blockedIps = ['127.0.0.2'];
canActivate(context: ExecutionContext): boolean {
const request: Request = context.switchToHttp().getRequest();
const ip = request.ip;
return !this.blockedIps.includes(ip);
}
}
Bước 3: Sử dụng guard
// users/users.controller.ts
import { UseGuards } from '@nestjs/common';
import { IPBlockGuard } from '../common/guards/ip-block.guard';
@UseGuards(IPBlockGuard)
@Get('safe')
getData() {
return { message: 'Chỉ IP hợp lệ mới được vào' };
}
Bài tập thực hành
Mục tiêu
Thực hành xây dựng Middleware, Interceptor và Guard như sau:
Yêu cầu
Middleware: kiểm tra
x-auth-token
có tồn tại trong header. Nếu không có, log ra cảnh báo.Interceptor: bọc dữ liệu trả về theo định dạng
{ success: true, data: ..., time: ... }
Guard: chặn truy cập từ IP
192.168.0.100
Áp dụng:
Middleware toàn cục
Interceptor toàn cục
Guard cho một route nhất định
Gợi ý test với Postman
Dùng
GET /users/safe
để kiểm tra guard chặn IPDùng
GET /users
không cóx-auth-token
để test middlewareXem định dạng response khi áp dụng Interceptor
Kết luận
Bạn đã học cách:
Viết và dùng Middleware để can thiệp trước xử lý controller
Dùng Interceptor để biến đổi dữ liệu trả về
Tạo Guard để kiểm tra phân quyền, IP hoặc token
Các khái niệm này là nền tảng để bảo mật và kiểm soát request trong ứng dụng NestJS quy mô lớn.
Last updated