Interceptors là gì

The statement also identifies plantations as significant uncontrolled interceptors of water.

She is producing large numbers of high-performance interceptor fighters to contend with any strategic air offensive that might be launched against her.

I would not say that we should dispense with air defence, though interceptor fighters are very expensive.

They have changed from an interceptor, ground support air force system to a highly offensive, attacking capability.

A great deal depends on the precise operation characteristics of the interceptor or strike aircraft.

Disclosure of information in this form would not be in the public interest, but the interceptor force continues to give satisfactory results.

Is the collaborative project based on the notion of an interceptor rôle only rather than a strike-reconnaissance rôle?

Is not this a medium-range nuclear bomber and not just an interceptor?

It is certainly a very fine manned interceptor fighter.

We have to ask whether we should give such financial priority to a cold war interceptor.

I am thinking particularly of the airborne early warning aircraft, the interceptor aircraft, ground radars and operational centres.

Once closed, the long-range interceptors —this is a curate's egg situation—cannot operate.

Remember, if the source code is open for developers then it is also open for interceptors.

Flown by instructor pilots, they are assigned a local defence role behind the main shield of our long range interceptors.

The manned interceptor has the virtue of range.

Các quan điểm của các ví dụ không thể hiện quan điểm của các biên tập viên Cambridge Dictionary hoặc của Cambridge University Press hay của các nhà cấp phép.

Interceptors

Contents

  • 1. First steps
  • 2. Controllers
  • 3. Providers
  • 4. Modules
  • 5. Middleware
  • 6. Exception filters
  • 7. Pipes
  • 8. Guards
  • 9. Interceptors
  • 10. Custom route decorators
  • Comments

Một Interceptor là một lớp được chú thích bằng decorator @Injectable[]. Các Interceptors phải implement interface NestInterceptor.

Các Interceptors có một tập hợp các khả năng hữu ích được lấy cảm hứng từ kỹ thuật lập trình hướng khía cạnh Aspect Oriented Programming [AOP]. Họ làm cho nó có thể:

  • ràng buộc logic bổ sung trước / sau khi thực thi phương thức
  • biến đổi kết quả trả về từ một hàm
  • biến đổi exception được ném ra từ một hàm
  • mở rộng hành vi function cơ bản
  • ghi đè hoàn toàn một function tùy thuộc vào các điều kiện cụ thể [ví dụ: cho mục đích lưu vào bộ nhớ đệm]

Basics

Với mỗi interceptor triển khai phương thức intercept[], phương thức này nhận 2 đối số. Đầu tiên là instance ExecutionContext [chinh xác là đối tượng giống như guards].  ExecutionContext kế thừa từ ArgumentsHost. Chúng ta đã xem ArgumentsHost trước đây trong chương exception filters. Ở đó, chúng tôi thấy rằng đó là một trình bao bọc xung quanh các đối số đã được chuyển cho trình xử lý ban đầu và chứa các mảng đối số khác nhau dựa trên loại ứng dụng. Bạn có thể tham khảo lại các exception filters để biết thêm về chủ đề này.

Execution context

Bằng cách mở rộng ArgumentsHost, ExecutionContext cũng bổ sung một số phương thức helper mới cung cấp chi tiết bổ sung về quy trình thực thi hiện tại. Những chi tiết này có thể hữu ích trong việc xây dựng các interceptors chung chung hơn có thể hoạt động trên nhiều controllers, phương thức và  execution contexts. Tìm hiểu thêm về ExecutionContext here.

Call handler

Đối số thứ hai là một CallHandler. CallHandler interface implements phương thức handle[], bạn có thể sử dụng phương thức này để gọi phương thức route handler tại một số điểm trong interceptor của bạn. Nếu bạn không gọi phương thức handle[] khi triển khai phương thức intercept[], thì phương thức route handler sẽ không được thực thi.

Cách tiếp cận này có nghĩa là phương thức intercept[] bao bọc luồng request/response một cách hiệu quả. Do đó, bạn có thể triển khai logic tùy chỉnh cả trước và sau khi thực thi route handler cuối cùng. Rõ ràng là bạn có thể viết mã trong phương thức intercept[] thực thi trước khi gọi handle[], nhưng làm thế nào để bạn ảnh hưởng đến những gì xảy ra sau đó? Vì phương thức handle[] trả về một Observable, chúng ta có thể sử dụng các toán tử RxJS mạnh mẽ để thao tác sâu hơn với response. Sử dụng thuật ngữ Lập trình hướng theo khía cạnh, lệnh gọi của route handler [tức là gọi handler[]] được gọi là Pointcut, cho biết rằng đó là điểm mà tại đó logic bổ sung của chúng ta được chèn vào.

Ví dụ: hãy xem xét một request POST /cats gửi đến. Yêu cầu này dành handler create[] được định nghĩa bên trong CatsController. Nếu một interceptor handle[] được gọi ở bất kỳ đâu trên đường đi, phương thức create[] sẽ không được thực thi. Sau khi handle[] được gọi [và khả năng quan sát của nó đã được trả về], handler create[] sẽ được kích hoạt. Và khi nhận được luồng response thông qua Observable, các hoạt động bổ sung có thể được thực hiện trên luồng và kết quả cuối cùng được trả lại cho người gọi.

Aspect interception

Trường hợp sử dụng đầu tiên mà chúng ta sẽ xem xét là sử dụng một interceptor ghi lại tương tác của người dùng [ví dụ: lưu trữ các cuộc gọi của người dùng, điều phối không đồng bộ các sự kiện hoặc tính toán dấu thời gian]. Chúng tôi hiển thị một LoggingInterceptor đơn giản bên dưới:

logging.interceptor.ts

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 {
    console.log['Before...'];

    const now = Date.now[];
    return next
      .handle[]
      .pipe[
        tap[[] => console.log[`After... ${Date.now[] - now}ms`]],
      ];
  }
}

HINT NestInterceptor là một interface chung ở đó T chỉ ra kiểu của một  Observable [hỗ trợ luồng response], và là kiểu value được bao bọc bởi Observable.

NOTICE Interceptors, giống như controllers, providers, guards, and so on, có thể inject dependencies quahàmconstructor.

handle[] trả về một RxJS Observable, chúng tôi có nhiều lựa chọn toán tử mà chúng tôi có thể sử dụng để thao tác luồng. Trong ví dụ trên, chúng tôi đã sử dụng toán tử tap[], gọi chức năng ghi nhật ký ẩn danh của chúng tôi khi kết thúc duyên dáng hoặc đặc biệt của luồng có thể quan sát, nhưng không can thiệp vào chu kỳ phản hồi.

Binding interceptors

Để thiết lập interceptor, chúng tôi sử dụng decorator @UseInterceptors[] được nhập từ gói @nestjs/common. Giống như  pipes và guards, các interceptors có thể là phạm vi controller, phạm vi phương thức hoặc phạm vi toàn cục.

cats.controller.ts

@UseInterceptors[LoggingInterceptor]
export class CatsController {}

HINT @UseInterceptors[] decorator được nhập từ gói @nestjs/common.

Sử dụng cấu trúc trên, mỗi route handler được xác định trong CatsController sẽ sử dụng LoggingInterceptor. Khi ai đó gọi endpoint GET /cats, bạn sẽ thấy đầu ra sau trong đầu ra chuẩn của mình:

Lưu ý rằng chúng tôi đã chuyển kiểu LoggingInterceptor [thay vì một instance], để lại trách nhiệm khởi tạo cho framework và cho phép chèn dependency injection. Giống như với pipes, guards, và exception filters, chúng tôi cũng có thể truyền một instance tại chỗ:

cats.controller.ts

@UseInterceptors[new LoggingInterceptor[]]
export class CatsController {}

Như đã đề cập, cấu trúc ở trên gắn interceptor vào mọi handler do controller này khai báo. Nếu chúng ta muốn giới hạn phạm vi của interceptor trong một phương thức duy nhất, chúng ta chỉ cần áp dụng decorator ở cấp phương thức.

Để thiết lập một interceptor toàn cục, chúng tôi sử dụng phương thức useGlobalInterceptors[] của instance ứng dụng Nest:

const app = await NestFactory.create[AppModule];
app.useGlobalInterceptors[new LoggingInterceptor[]];

Các interceptor toàn cục được sử dụng trên toàn bộ ứng dụng, cho mọi controler và mọi route hander. Về mặt dependency injection, các interceptor toàn cục được đăng ký từ bên ngoài của bất kỳ mô-đun nào [với useGlobalInterceptors[], như trong ví dụ trên] không thể inject dependencies vì điều này được thực hiện bên ngoài ngữ cảnh của bất kỳ mô-đun nào. Để giải quyết vấn đề này, bạn có thể thiết lập một interceptor trực tiếp từ bất kỳ mô-đun nào bằng cách sử dụng cấu trúc sau:

app.module.ts

import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';

@Module[{
  providers: [
    {
      provide: APP_INTERCEPTOR,
      useClass: LoggingInterceptor,
    },
  ],
}]
export class AppModule {}

HINT Khi sử dụng cách tiếp cận này để thực hiện dependency injection cho interceptor, lưu ý rằng bất kể mô-đun mà cấu trúc này được sử dụng là gì, trên thực tế, interceptor là toàn cục. Điều này nên được thực hiện ở đâu? Chọn mô-đun nơi interceptor [LoggingInterceptor trong ví dụ trên] được định nghĩa. Ngoài ra, useClass không phải là cách duy nhất để giải quyết vấn đề đăng ký provider tùy chỉnh. Xem thêm here.

Response mapping

Chúng ta đã biết rằng handle[] trả về một Observable. Luồng chứa giá trị được trả về từ route hander và do đó chúng ta có thể dễ dàng thay đổi nó bằng cách sử dụng toán tử map[] của RxJS.

WARNING Tính năng response mapping không hoạt động với thư viện riêng response strategy [sử dụng @Res[] trực tiepeps đối tượng bị cấm].

Chúng ta tạo TransformInterceptor, điều này sẽ sửa đổi từng response theo cách nhỏ để chứng minh quy trình. Nó sẽ sử dụng toán tử RxJS’s map[] để gán đối tượng response cho thuộc tính dữ liệu của một đối tượng mới được tạo, trả lại đối tượng mới cho client.

transform.interceptor.ts

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Response {
  data: T;
}

@Injectable[]
export class TransformInterceptor implements NestInterceptor {
  intercept[context: ExecutionContext, next: CallHandler]: Observable {
    return next.handle[].pipe[map[data => [{ data }]]];
  }
}

HINT Nest interceptors làm việc với cả đồng bộ và không đồng bộ phương thức intercept[]. You can simply switch the method to async if necessary.

Với cách xây dựng ở trên, khi ai đó gọi endpoint GET /cats, response sẽ giống như sau [giả sử rằng route hander trả về một mảng trống []]:

Interceptors có giá trị lớn trong việc tạo ra các giải pháp có thể tái sử dụng cho các yêu cầu xảy ra trên toàn bộ ứng dụng. Ví dụ, hãy tưởng tượng chúng ta cần chuyển đổi mỗi lần xuất hiện của giá trị null thành một chuỗi rỗng ”. Chúng tôi có thể làm điều đó bằng cách sử dụng một dòng mã và liên kết Interceptors trên toàn cục để nó sẽ tự động được sử dụng bởi mỗi handler đã đăng ký.

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

@Injectable[]
export class ExcludeNullInterceptor implements NestInterceptor {
  intercept[context: ExecutionContext, next: CallHandler]: Observable {
    return next
      .handle[]
      .pipe[map[value => value === null ? '' : value ]];
  }
}

Exception mapping

Một trường hợp sử dụng thú vị khác là tận dụng toán tử catchError[] của RxJS để ghi đè các ngoại lệ đã ném:

errors.interceptor.ts

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  BadGatewayException,
  CallHandler,
} from '@nestjs/common';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

@Injectable[]
export class ErrorsInterceptor implements NestInterceptor {
  intercept[context: ExecutionContext, next: CallHandler]: Observable {
    return next
      .handle[]
      .pipe[
        catchError[err => throwError[new BadGatewayException[]]],
      ];
  }
}

Stream overriding

Có một số lý do tại sao đôi khi chúng ta có thể muốn ngăn chặn hoàn toàn việc gọi handler và thay vào đó trả về một giá trị khác. Một ví dụ rõ ràng là triển khai bộ nhớ cache để cải thiện thời gian phản hồi. Chúng ta hãy xem xét một interceptor bộ nhớ cache đơn giản trả về phản hồi của nó từ bộ nhớ cache. Trong một ví dụ thực tế, chúng tôi muốn xem xét các yếu tố khác như TTL, vô hiệu bộ nhớ cache, kích thước bộ nhớ cache, v.v., nhưng điều đó nằm ngoài phạm vi của cuộc thảo luận này. Ở đây chúng tôi sẽ cung cấp một ví dụ cơ bản thể hiện khái niệm chính.

cache.interceptor.ts

import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable, of } from 'rxjs';

@Injectable[]
export class CacheInterceptor implements NestInterceptor {
  intercept[context: ExecutionContext, next: CallHandler]: Observable {
    const isCached = true;
    if [isCached] {
      return of[[]];
    }
    return next.handle[];
  }
}

CacheInterceptor của chúng tôi có biến isCached được mã hóa cứng và response được mã hóa cứng []. Điểm quan trọng cần lưu ý là chúng ta trả về một luồng mới ở đây, được tạo bởi toán tử RxJS of[], do đó route handler sẽ không được gọi. Khi ai đó gọi một endpoint sử dụng CacheInterceptor, phản hồi [một mảng trống, được mã hóa cứng] sẽ được trả về ngay lập tức. Để tạo giải pháp chung, bạn có thể tận dụng Reflector và tạo decorator tùy chỉnh. Reflector được mô tả kỹ trong chương guards.

More operators

Khả năng thao tác luồng bằng toán tử RxJS cho chúng ta nhiều khả năng. Hãy xem xét một trường hợp sử dụng phổ biến khác. Hãy tưởng tượng bạn muốn xử lý thời gian chờ theo request route. Khi endpoint của bạn không trả lại bất kỳ thứ gì sau một khoảng thời gian, bạn muốn kết thúc bằng response lỗi. Cấu trúc sau cho phép điều này:

timeout.interceptor.ts

import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from '@nestjs/common';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { catchError, timeout } from 'rxjs/operators';

@Injectable[]
export class TimeoutInterceptor implements NestInterceptor {
  intercept[context: ExecutionContext, next: CallHandler]: Observable {
    return next.handle[].pipe[
      timeout[5000],
      catchError[err => {
        if [err instanceof TimeoutError] {
          return throwError[new RequestTimeoutException[]];
        }
        return throwError[err];
      }],
    ];
  };
};

Sau 5 giây, quá trình xử lý request sẽ bị hủy. Bạn cũng có thể thêm logic tùy chỉnh trước khi ném RequestTimeoutException [ví dụ: giải phóng tài nguyên].

[Nguồn //docs.nestjs.com/interceptors]

Pages: 1 2 3 4 5 6 7 8 9 10

Chủ Đề