Khám Phá Execution Context trong NestJS
Execution Context là một khái niệm cơ bản nhưng cực kỳ quan trọng trong phát triển ứng dụng bằng NestJS. Nó cung cấp một abstraction nhằm xác định rõ ngữ cảnh mà một handler (phương thức) được thực thi. Việc hiểu rõ Execution Context giúp bạn phát triển các tính năng như middleware, guards, interceptors, và filters một cách hiệu quả hơn.
Các Khái Niệm Quan Trọng Liên Quan Đến Execution Context
-
Handler (Phương Thức)
Đây là phương thức cụ thể sẽ được thực thi khi có yêu cầu đến một endpoint trong controller. -
Class
Class chứa handler, thường là controller hoặc provider trong NestJS. -
ArgumentsHost
- Đóng vai trò như một abstraction giúp truy cập đến các argument của handler.
- Hỗ trợ nhiều kiểu execution context khác nhau:
- HTTP
- RPC (Remote Procedure Call)
- WebSocket
-
ContextType
- Xác định loại ngữ cảnh mà handler đang hoạt động, bao gồm:
http
rpc
ws
(WebSocket)
- Xác định loại ngữ cảnh mà handler đang hoạt động, bao gồm:
-
ArgumentsHost Methods
switchToHttp()
: Truy cập thông tin HTTP như request và response.switchToRpc()
: Truy cập dữ liệu RPC.switchToWs()
: Truy cập dữ liệu WebSocket.getArgs()
: Lấy danh sách toàn bộ các arguments.getType()
: Trả về kiểu context (http
,rpc
,ws
).
Ví Dụ Thực Tế về Sử Dụng Execution Context
Xây Dựng Một Guard
Guard được sử dụng để kiểm tra quyền truy cập trước khi handler được thực thi.
typescript
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const user = request.user;
return user && user.isAuthenticated; // Kiểm tra người dùng đã đăng nhập chưa
}
}
Tạo Custom Interceptor
Interceptor có thể được sử dụng để xử lý logic trước hoặc sau khi handler chạy.
typescript
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
console.log(`Incoming request: ${request.method} ${request.url}`);
return next.handle().pipe(
tap(() => console.log(`Request handled successfully`)),
);
}
}
Tạo Custom Exception Filter
Filter được sử dụng để xử lý exception dựa trên Execution Context.
typescript
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse();
const request = ctx.getRequest();
const status = exception.getStatus();
response.status(status).json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
Khi Nào Cần Sử Dụng Execution Context?
-
Xử Lý Xác Thực và Phân Quyền
- Kiểm tra quyền truy cập của người dùng.
- Định nghĩa các điều kiện trước khi cho phép truy cập vào handler.
-
Ghi Log hoặc Đo Thời Gian Thực Thi
- Interceptor giúp theo dõi thời gian xử lý hoặc ghi lại thông tin log của request.
-
Tùy Chỉnh Phản Hồi Lỗi
- Filters giúp xác định cách trả lỗi một cách đồng bộ với API của bạn.
-
Tích Hợp với Các Giao Thức Khác như WebSocket hoặc gRPC
- Sử dụng các phương thức như
switchToWs()
hoặcswitchToRpc()
để làm việc với các giao thức này.
- Sử dụng các phương thức như
Tóm Tắt
Execution Context trong NestJS cung cấp một abstraction để truy cập thông tin liên quan đến quá trình thực thi của handler, bao gồm request, response và các argument. Kiến thức về Execution Context đặc biệt hữu ích khi bạn cần kiểm soát hoặc tùy chỉnh logic trong toàn cục (guards, interceptors, filters) mà không làm ảnh hưởng đến handler cụ thể.
Liên Quan
Hướng Dẫn Chi Tiết về Execution Context trong NestJS
Tham khảo thêm đoạn mã ví dụ tại repository này và bài viết gốc tại trang cá nhân của mình.
source: viblo