Guards, interceptors, pipes, exception filters

↑ 6.2 NestJS · ← Предыдущая · → Следующая

По желанию~4 мин чтенияУровень: junior

Зачем это на собесе

Порядок обработки запроса в Nest и роль каждого компонента.

Объяснение

Порядок: middleware → guards → interceptors (до) → pipes → handler → interceptors (после) → exception filters.

КомпонентНазначениеАналог в ASP.NET Core
Middlewareнизкоуровневая обработка запросаmiddleware
Guardразрешить/запретить (canActivate)authorization filter/policy
Interceptorобернуть выполнение: логирование, кэш, преобразование ответа, таймаутaction/result filter
Pipeпреобразование и валидация параметровmodel binding + validation
Exception filterпреобразование исключения в ответIExceptionHandler
@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}
  canActivate(ctx: ExecutionContext): boolean {
    const roles = this.reflector.get<string[]>("roles", ctx.getHandler());
    const user = ctx.switchToHttp().getRequest().user;
    return !roles || roles.some(r => user?.roles?.includes(r));
  }
}
 
@Injectable()
export class TimingInterceptor implements NestInterceptor {
  intercept(_: ExecutionContext, next: CallHandler) {
    const t = Date.now();
    return next.handle().pipe(tap(() => console.log(`${Date.now() - t} ms`)));
  }
}
 
@Catch(HttpException)
export class HttpErrorFilter implements ExceptionFilter {
  catch(e: HttpException, host: ArgumentsHost) {
    const res = host.switchToHttp().getResponse();
    res.status(e.getStatus()).json({ status: e.getStatus(), message: e.message });
  }
}
 
@UseGuards(JwtAuthGuard, RolesGuard)
@UseInterceptors(TimingInterceptor)
@Get("admin") admin() {}

Применение: на метод, контроллер или глобально (app.useGlobalGuards, провайдеры APP_GUARD).

Нюансы и подводные камни

  • Глобальные guards, зарегистрированные через app.use…, не получают DI: используйте APP_GUARD.
  • Порядок декораторов и уровней (global → controller → method) важен.
  • Исключения вне HTTP-контекста (микросервисы, WebSocket) требуют своих фильтров.
  • Не помещайте бизнес-логику в interceptor.

Практика

  1. Реализуйте роль-guard с кастомным декоратором @Roles().
  2. Сделайте interceptor кэширования ответов.
  3. Единый фильтр ошибок с traceId.

Вопросы с ответами

Связанные темы