Що таке middleware у NestJS і чим воно відрізняється від guards?
Проміжне ПЗ в NestJS
Проміжне ПЗ в NestJS ідентичне проміжному ПЗ Express — це функція, яка виконується перед обробником маршруту і має доступ до req, res та next. Однак NestJS обгортає його у формат класу, який підтримує впровадження залежностей.
Створення Проміжного ПЗ
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();
}
}Функціональне Проміжне ПЗ (Просте)
// Клас не потрібен — лише функція
export function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
console.log(`${req.method} ${req.url}`);
next();
}Реєстрація Проміжного ПЗ
На відміну від Guards, Pipes та Interceptors, проміжне ПЗ NestJS реєструється в модулі за допомогою методу configure():
import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
@Module({
controllers: [UsersController, ProductsController],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*'); // всі маршрути
consumer
.apply(AuthMiddleware)
.exclude(
{ path: 'auth/login', method: RequestMethod.POST },
{ path: 'auth/register', method: RequestMethod.POST },
)
.forRoutes(UsersController); // всі маршрути UsersController
consumer
.apply(RateLimitMiddleware)
.forRoutes({ path: 'api/*', method: RequestMethod.ALL });
// Кілька проміжних ПЗ в порядку
consumer
.apply(CorsMiddleware, HelmetMiddleware, LoggerMiddleware)
.forRoutes('*');
}
}Практичний Приклад: Проміжне ПЗ для ID Запиту
import { v4 as uuid } from 'uuid';
@Injectable()
export class RequestIdMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const requestId = req.headers['x-request-id'] as string || uuid();
req['requestId'] = requestId;
res.setHeader('x-request-id', requestId);
next();
}
}Проміжне ПЗ vs Guards vs Interceptors
| Особливість | Проміжне ПЗ | Guard | Interceptor |
|---|---|---|---|
| Доступ до ExecutionContext | ❌ | ✅ | ✅ |
| Доступ до метаданих (Reflector) | ❌ | ✅ | ✅ |
| Виконується перед guards | ✅ | — | — |
| Підтримка DI | ✅ | ✅ | ✅ |
| Може перервати запит | ✅ | ✅ | ✅ |
| Може змінити відповідь | ✅ | ❌ | ✅ |
| Призначення | Логування, CORS, парсинг тіла | Аутентифікація, ролі | Трансформація, кешування, тайминг |
Порядок Виконання
Запит
→ Проміжне ПЗ (в порядку реєстрації)
→ Guards
→ Interceptors (до)
→ Pipes
→ Обробник
→ Interceptors (після)
→ ВідповідьПроміжне ПЗ виконується перед guards і не має доступу до метаданих NestJS — використовуйте guards для аутентифікації/авторизації, проміжне ПЗ для нижчого рівня (логування, CORS, парсинг запитів).
Резюме
Проміжне ПЗ NestJS працює як проміжне ПЗ Express, але з синтаксисом класу та підтримкою DI. Реєструйте його через configure() в модулі. Використовуйте проміжне ПЗ для інфраструктурних питань (логування, ID запитів, обмеження швидкості за допомогою пакетів Express). Використовуйте Guards для аутентифікації/авторизації — вони мають доступ до метаданих маршруту та повного ExecutionContext.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.