Что такое middleware в NestJS?

MiddleNestJS · Backend·Обновлено 3 июля 2026
Коротко
Middleware в NestJS — это функция, которая выполняется до обработчика маршрута и имеет доступ к объектам запроса (req), ответа (res) и функции next(). Используется для логирования, аутентификации, трансформации запросов и других сквозных задач.

Middleware в NestJS

Middleware — это промежуточный обработчик, встроенный в цепочку обработки HTTP-запроса между клиентом и конечным обработчиком маршрута. Концепция взята из Express.js, на котором NestJS основан по умолчанию.

Что умеет middleware

  • Выполнять произвольный код до обработки запроса
  • Изменять объекты req и res
  • Завершить цикл запрос-ответ досрочно
  • Вызвать следующий middleware через next()
  • Если next() не вызван — запрос «зависает»

Два способа создания

Класс-based middleware — рекомендованный подход в 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) {
    // Логируем метод и URL входящего запроса
    console.log(`[${req.method}] ${req.url}`);
    next(); // Передаём управление дальше
  }
}

Функциональный middleware — простой вариант без DI:

import { Request, Response, NextFunction } from 'express';

export function loggerMiddleware(req: Request, res: Response, next: NextFunction) {
  console.log(`[${req.method}] ${req.url}`);
  next();
}

Подключение через AppModule

Middleware подключается в модуле через метод configure() с помощью MiddlewareConsumer:

import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { LoggerMiddleware } from './logger.middleware';
import { UsersModule } from './users/users.module';

@Module({
  imports: [UsersModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      // Применяем только к маршрутам /users с методом GET
      .forRoutes({ path: 'users', method: RequestMethod.GET });
  }
}

Гибкость настройки маршрутов

consumer
  .apply(AuthMiddleware, LoggerMiddleware) // Цепочка middleware
  .exclude(
    { path: 'auth/login', method: RequestMethod.POST }, // Исключаем публичный эндпоинт
  )
  .forRoutes('*'); // Применяем ко всем маршрутам

Middleware vs Guards vs Interceptors

Инструмент Порядок выполнения Типичное применение
Middleware 1-й Логирование, базовая трансформация req
Guard 2-й Аутентификация и авторизация
Interceptor 3-й (до/после) Трансформация ответа, кэширование
Pipe 4-й Валидация и трансформация данных

Важные особенности

Класс-based middleware поддерживает инъекцию зависимостей через @Injectable(), что позволяет использовать сервисы внутри middleware. Функциональный вариант этой возможности лишён.

Global middleware можно подключить через app.use() в main.ts, но такой middleware не имеет доступа к DI-контейнеру NestJS и является чисто Express-уровневым.

Что хочет услышать интервьюер

Понимание места middleware в жизненном цикле запроса NestJS (до Guards, Pipes, Interceptors)

Знание двух способов создания middleware: класс через NestMiddleware и функциональный

Умение подключить middleware через MiddlewareConsumer в модуле с настройкой маршрутов

Понимание разницы между middleware и Guards/Interceptors — когда что применять

Знание, что класс-based middleware поддерживает Dependency Injection, а функциональный — нет

Пример: Класс-based middleware с инъекцией зависимости

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
import { AuthService } from '../auth/auth.service';

@Injectable()
export class TokenMiddleware implements NestMiddleware {
  constructor(private readonly authService: AuthService) {}

  async use(req: Request, res: Response, next: NextFunction) {
    const token = req.headers['authorization']?.split(' ')[1];

    if (token) {
      // Декодируем токен и кладём пользователя в объект запроса
      req['user'] = await this.authService.decodeToken(token);
    }

    next();
  }
}

Пример: Подключение middleware в модуле

import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { TokenMiddleware } from './common/token.middleware';
import { UsersModule } from './users/users.module';
import { AuthModule } from './auth/auth.module';

@Module({
  imports: [UsersModule, AuthModule],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(TokenMiddleware)
      .exclude(
        // Логин и регистрация доступны без токена
        { path: 'auth/login', method: RequestMethod.POST },
        { path: 'auth/register', method: RequestMethod.POST },
      )
      .forRoutes('*'); // Применяем ко всем остальным маршрутам
  }
}

Типичные ошибки

Путают middleware с Guards — утверждают, что middleware — правильное место для авторизации, хотя Guards лучше подходят для этого

Забывают вызвать next() внутри middleware, из-за чего запрос зависает и не доходит до контроллера

Не знают, что global middleware через app.use() в main.ts не имеет доступа к DI-контейнеру

Не понимают порядок выполнения: думают, что Interceptors выполняются раньше Middleware

Не используют exclude() для исключения публичных маршрутов, пытаясь вместо этого добавлять условия внутри самого middleware

Лучшие курсы по теме

Иконка молнииНовый
изображение курса

Продвинутый Python

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга5.0
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Golang - Templ Fiber HTMX

Антон Ларичев
AI-тренажерыAI-тренажеры
Практика в студииПрактика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Основы C#

Антон Ларичев
AI-тренажерыAI-тренажеры
Гарантия
Бонусы
иконка звёздочки рейтинга4.3
3 999 ₽ 6 990 ₽
Подробнее