Guards, interceptors, pipes, exception filters
↑ 6.2 NestJS · ← Предыдущая · → Следующая
Зачем это на собесе
Порядок обработки запроса в 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.
Практика
- Реализуйте роль-guard с кастомным декоратором
@Roles(). - Сделайте interceptor кэширования ответов.
- Единый фильтр ошибок с
traceId.
Вопросы с ответами
Чем guard отличается от middleware?
Guard знает о контексте исполнения (какой handler будет вызван) и решает доступ, middleware — нет.
Что делает interceptor?
Оборачивает вызов handler: код до и после, преобразование результата и ошибок.