Какова разница между перехватчиками и посредниками?
При работе с NestJS, многие начинающие разработчики могут сталкиваться с терминами "перехватчики" и "посредники" (middleware). Эти два концепта часто путают, однако они выполняют разные задачи в архитектуре приложения. Давайте разберёмся в их основных различиях и увидим примеры кода.
Определения
Промежуточное ПО (Middleware) — это функции, которые обрабатываются перед тем, как запрос достигнет маршрутизатора. Они могут использоваться для выполнения операций, таких как аутентификация, логирование, модификация объекта запроса и так далее. Middleware имеет доступ к объектам request
, response
и функции next
, чтобы продолжить выполнение последовательности.
Перехватчики (Interceptors) — это функции, которые могут обрабатывать запросы и ответы во время обработки контроллером. Они обеспечивают более мощный способ для работы с результатами выполнения метода контроллера. Перехватчики могут трансформировать результат, модифицировать параметры запроса, а также реализовывать дополнительную логику перед возвращением ответа.
Пример использования Middleware
Давайте рассмотрим примеры кода для каждого из них.
Пример middleware
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: () => void) {
console.log(`Request... Method: ${req.method} URL: ${req.url}`);
next(); // Необходимо для перехода к следующему middleware или маршруту
}
}
// Регистрация middleware в модуле
import { Module, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
@Module({
controllers: [AppController],
})
export class AppModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*'); // Применить ко всем маршрутам
}
}
Пример использования Interceptor
Теперь давайте посмотрим на пример перехватчика.
Пример interceptor
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 now = Date.now();
return next
.handle()
.pipe(
tap(() => console.log(`Response... ${Date.now() - now}ms`)),
);
}
}
// Регистрация interceptor в модуле
import { Module } from '@nestjs/common';
import { APP_INTERCEPTOR } from '@nestjs/core';
@Module({
providers: [
{
provide: APP_INTERCEPTOR,
useClass: LoggingInterceptor,
},
],
})
export class AppModule {}
Заключение
Оба инструмента полезны в различных ситуациях, и понимание их различий поможет вам лучше проектировать свои приложения на NestJS.