← Назад к вопросам

Какие знаешь этапы обработки запросов в NestJS?

2.0 Middle🔥 121 комментариев
#Node.js и JavaScript#Фреймворки и библиотеки

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Этапы обработки запросов в NestJS

NestJS построен на базе Express.js и предоставляет мощный механизм для обработки HTTP-запросов. Давайте разберём полный цикл жизни запроса от входа до отправки ответа.

Основная архитектура обработки

Порядок выполнения:

  1. Middleware → 2. Guards → 3. Interceptors (до контроллера) → 4. Pipes (валидация) → 5. Controller → 6. Service → 7. Interceptors (после контроллера) → 8. Exception Filters → 9. Response sent

Этап 1: Middleware

Middleware выполняется первым и имеет доступ к объектам Request и Response. Используется для общей обработки: логирования, парсинга body, аутентификации и т.п.

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.path}`);
    next();
  }
}

// Регистрация в модуле
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes("*");
  }
}

Этап 2: Guards (Охранники)

Guards определяют, есть ли у пользователя доступ к конкретному маршруту. Используются для проверки аутентификации, авторизации и ролей.

import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";

@Injectable()
export class JwtGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const token = request.headers.authorization?.split(" ")[1];
    
    if (!token) return false;
    
    try {
      // Проверка и декодирование JWT
      const decoded = jwt.verify(token, process.env.JWT_SECRET);
      request.user = decoded;
      return true;
    } catch {
      return false;
    }
  }
}

// Использование
@Controller("users")
export class UsersController {
  @Get()
  @UseGuards(JwtGuard)
  findAll() {
    return this.usersService.findAll();
  }
}

Этап 3: Interceptors (Перехватчики)

Interceptors позволяют перехватить запрос до и после обработки. Используются для логирования, трансформации данных, обработки ошибок, кэширования.

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> {
    console.log("Before...");
    const now = Date.now();
    
    return next.handle().pipe(
      tap(() => {
        console.log(`After... ${Date.now() - now}ms`);
      })
    );
  }
}

// Применение на уровне контроллера или метода
@Controller("cats")
@UseInterceptors(LoggingInterceptor)
export class CatsController {
  @Get()
  findAll() {
    return this.catsService.findAll();
  }
}

Этап 4: Pipes (Трубы)

Pipes выполняют две основные функции: валидацию данных и трансформацию. Они обрабатывают параметры маршрута, query-параметры и body запроса.

import { PipeTransform, Injectable, BadRequestException } from "@nestjs/common";

@Injectable()
export class ParseIntPipe implements PipeTransform<string, number> {
  transform(value: string): number {
    const val = parseInt(value, 10);
    if (isNaN(val)) {
      throw new BadRequestException("Validation failed");
    }
    return val;
  }
}

@Get(":id")
async getUser(
  @Param("id", ParseIntPipe) id: number
) {
  return this.usersService.findOne(id);
}

Встроенные Pipes:

  • ParseIntPipe — конвертация в число
  • ParseBoolPipe — конвертация в boolean
  • ValidationPipe — валидация через класс-валидатор

Этап 5: Controller (Контроллер)

После всех проверок запрос поступает в метод контроллера. Контроллер обрабатывает параметры, вызывает сервисы и возвращает данные.

@Controller("users")
export class UsersController {
  constructor(private readonly usersService: UsersService) {}

  @Get()
  async findAll(@Query("limit") limit: number = 10) {
    return this.usersService.findAll(limit);
  }

  @Post()
  @UseInterceptors(ValidationPipe)
  async create(@Body() createUserDto: CreateUserDto) {
    return this.usersService.create(createUserDto);
  }
}

Этап 6: Service (Сервис)

Сервис содержит бизнес-логику: работа с БД, вычисления, интеграции с внешними API и т.п.

@Injectable()
export class UsersService {
  constructor(@InjectRepository(User) private usersRepository: Repository<User>) {}

  async findAll(limit: number) {
    return this.usersRepository.find({ take: limit });
  }

  async create(createUserDto: CreateUserDto) {
    const user = this.usersRepository.create(createUserDto);
    return this.usersRepository.save(user);
  }
}

Этап 7: Interceptors (Постобработка)

После того, как контроллер вернул ответ, Interceptor может перехватить результат для трансформации или логирования.

Этап 8: Exception Filters (Фильтры исключений)

Если на любом из этапов произойдёт ошибка, она будет перехвачена Exception Filter и преобразована в HTTP-ответ.

import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from "@nestjs/common";

@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const ctx = host.switchToHttp();
    const response = ctx.getResponse();
    const status = exception.getStatus();

    response.status(status).json({
      statusCode: status,
      message: exception.getResponse(),
      timestamp: new Date().toISOString(),
    });
  }
}

// Применение
@UseFilters(HttpExceptionFilter)
@Controller("users")
export class UsersController {}

Полный пример обработки запроса

// Запрос: POST /users { "name": "John", "email": "john@example.com" }

// 1. Middleware проверяет аутентификацию и логирует
// 2. Guard проверяет, есть ли доступ
// 3. Interceptor логирует начало обработки
// 4. Pipe валидирует CreateUserDto через class-validator
// 5. Controller получает валидированные данные
// 6. Service сохраняет пользователя в БД
// 7. Interceptor преобразует ответ
// 8. Если ошибка — Exception Filter её перехватит
// 9. Ответ отправляется клиенту

Важные моменты

  • Порядок имеет значение — Guards срабатывают раньше Pipes, это критично для безопасности
  • Глобальные vs локальные — можно применять на уровне модуля, контроллера или метода
  • Асинхронные операции — все эти компоненты могут быть асинхронными
  • Тестирование — каждый компонент можно тестировать отдельно благодаря модульной архитектуре

Понимание этапов обработки запроса критично для написания чистого и безопасного кода в NestJS.

Какие знаешь этапы обработки запросов в NestJS? | PrepBro