☰ Mục lục series
Tài liệu NestJS tiếng Việt
  1. Nhập môn (Overview)
    1. Giới thiệu
    2. First steps
    3. Controllers
    4. Providers
    5. Modules
    6. Middleware
    7. Exception filters
    8. Pipes
    9. Guards
    10. Interceptors
    11. Custom decorators
  2. Nền tảng (Fundamentals)
    1. Custom providers
    2. Asynchronous providers
    3. Dynamic modules
    4. Injection scopes
    5. Circular dependency
    6. Module reference
    7. Lazy-loading modules
    8. Execution context
    9. Lifecycle events
    10. Discovery service
    11. Platform agnosticism
    12. Testing
  3. Kỹ thuật (Techniques)
    1. Configuration
    2. Database (SQL)
    3. MongoDB
    4. Validation
    5. Caching
    6. Serialization
    7. Versioning
    8. Task scheduling
    9. Queues
    10. Logging
    11. Cookies
    12. Events
    13. Compression
    14. File upload
    15. Streaming files
    16. HTTP module
    17. Session
    18. MVC
    19. Performance (Fastify)
    20. Server-Sent Events
  4. Bảo mật (Security)
    1. Authentication
    2. Authorization
    3. Encryption & Hashing
    4. Helmet
    5. CORS
    6. CSRF
    7. Rate limiting
    8. Vòng đời request
  5. OpenAPI (Swagger)
    1. Introduction
    2. Types and parameters
    3. Operations
    4. Security
    5. Mapped types
    6. Decorators
    7. CLI plugin
    8. Other features
  6. Recipes
    1. REPL
    2. CRUD generator
    3. SWC (fast compiler)
    4. Passport (auth)
    5. Hot reload
    6. MikroORM
    7. Router module
    8. Health checks (Terminus)
    9. CQRS
    10. Prisma
    11. Serve static
    12. Commander
    13. Async local storage
  7. WebSockets
    1. Gateways
    2. Exception filters
    3. Pipes
    4. Guards
    5. Interceptors
    6. Adapters
  8. Microservices
    1. Overview
    2. Redis
    3. MQTT
    4. NATS
    5. RabbitMQ
    6. Kafka
    7. gRPC
    8. Custom transporters
    9. Exception filters
    10. Pipes
    11. Pre-request hooks
    12. Guards
    13. Interceptors
  9. GraphQL
    1. Quick start
    2. Resolvers
    3. Mutations
    4. Subscriptions
    5. Scalars
    6. Directives
    7. Interfaces
    8. Unions and enums
    9. Field middleware
    10. Mapped types
    11. Plugins
    12. Complexity
    13. Extensions
    14. CLI plugin
    15. Generating SDL
    16. Sharing models
    17. Other features
    18. Federation
  10. CLI & triển khai
    1. CLI overview
    2. Workspaces
    3. Libraries
    4. Usage
    5. Scripts
    6. Deployment
    7. Standalone apps
  11. FAQ
    1. Serverless
    2. HTTP adapter
    3. Keep-Alive connections
    4. Global path prefix
    5. Raw body
    6. Hybrid application
    7. HTTPS & multiple servers
    8. Common errors
  12. Phụ lục
    1. Bảng thuật ngữ
Microservices

Exception filter (Exception filters)

Bản dịch từ docs.nestjs.com/microservices/exception-filters

Sự khác biệt duy nhất giữa lớp exception filter của HTTP và lớp tương ứng của microservices là thay vì throw HttpException, bạn nên dùng RpcException.

throw new RpcException('Invalid credentials.');

Gợi ý Class RpcException được import từ package @nestjs/microservices.

Cảnh báo Một event handler không có response stream. Một filter re-throw lỗi cho handler @EventPattern sẽ khiến lỗi đó không đi đến đâu cả, vì vậy hãy xử lý lỗi ngay trong filter.

Với ví dụ trên, Nest sẽ xử lý exception được throw và trả về object error với cấu trúc sau:

{
  "status": "error",
  "message": "Invalid credentials."
}

Filter

Exception filter của microservices hoạt động tương tự exception filter của HTTP, chỉ khác một điểm nhỏ. Method catch() phải trả về một Observable.

import { Catch, RpcExceptionFilter, ArgumentsHost } from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { RpcException } from '@nestjs/microservices';

@Catch(RpcException)
export class ExceptionFilter implements RpcExceptionFilter<RpcException> {
  catch(exception: RpcException, host: ArgumentsHost): Observable<any> {
    return throwError(() => exception.getError());
  }
}
import { Catch } from '@nestjs/common';
import { throwError } from 'rxjs';

@Catch(RpcException)
export class ExceptionFilter {
  catch(exception, host) {
    return throwError(() => exception.getError());
  }
}

Cảnh báo Exception filter global cho microservices không được bật theo mặc định khi dùng hybrid application.

Ví dụ sau dùng một filter method-scoped được khởi tạo thủ công. Giống như với ứng dụng dựa trên HTTP, bạn cũng có thể dùng filter controller-scoped (nghĩa là, thêm decorator @UseFilters() lên đầu class controller).

@UseFilters(new ExceptionFilter())
@MessagePattern({ cmd: 'sum' })
accumulate(data: number[]): number {
  return (data || []).reduce((a, b) => a + b);
}
@UseFilters(new ExceptionFilter())
@MessagePattern({ cmd: 'sum' })
accumulate(data) {
  return (data || []).reduce((a, b) => a + b);
}

Kế thừa (Inheritance)

Thông thường, bạn sẽ tạo các exception filter được tùy chỉnh hoàn toàn để đáp ứng nhu cầu của ứng dụng. Tuy nhiên, có những use case mà bạn chỉ muốn đơn giản là kế thừa exception filter cốt lõi (core), và override hành vi dựa trên một số yếu tố nhất định.

Để giao (delegate) việc xử lý exception cho filter cơ sở, bạn cần kế thừa BaseExceptionFilter và gọi method catch() đã được kế thừa.

import { Catch, ArgumentsHost } from '@nestjs/common';
import { BaseRpcExceptionFilter } from '@nestjs/microservices';

@Catch()
export class AllExceptionsFilter extends BaseRpcExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    return super.catch(exception, host);
  }
}
import { Catch } from '@nestjs/common';
import { BaseRpcExceptionFilter } from '@nestjs/microservices';

@Catch()
export class AllExceptionsFilter extends BaseRpcExceptionFilter {
  catch(exception, host) {
    return super.catch(exception, host);
  }
}

Đoạn code trên chỉ là một “vỏ” (shell) minh họa cách tiếp cận. Trong thực tế, exception filter mở rộng của bạn sẽ chứa business logic riêng (ví dụ xử lý các điều kiện khác nhau).

Ghi chú người dịch Ở PHP/Laravel, đây tương đương với việc bạn tạo một ExceptionHandler tùy chỉnh kế thừa từ handler mặc định và override method render(), nhưng vẫn gọi parent::render() cho các case bạn không muốn tự xử lý. Cơ chế “kế thừa rồi gọi lại super” giúp bạn chỉ can thiệp vào đúng phần logic cần thay đổi, còn lại để framework xử lý như cũ.

Nội dung gốc: NestJS Documentation © Kamil Myśliwiec, giấy phép MIT. Bản dịch và ghi chú: Lê Văn Dũng.