Guards, Interceptors & Pipes
Aplique autenticação, validação, logging e transformação de resposta com guards, interceptors e pipes do NestJS 11.
Receita
Cartão de receita de referência rápida - pronto para copiar e colar.
import { Controller, Get, Param, UseGuards, UseInterceptors, UsePipes, ValidationPipe } from "@nestjs/common";
import { AuthGuard } from "./auth.guard.js";
import { LoggingInterceptor } from "./logging.interceptor.js";
@Controller("users")
@UseGuards(AuthGuard)
@UseInterceptors(LoggingInterceptor)
export class UsersController {
@Get(":id")
@UsePipes(ValidationPipe)
findOne(@Param("id") id: string) {
return { id };
}
}Ordem de execução: Middleware -> Guards -> Interceptors (antes) -> Pipes -> Handler -> Interceptors (depois) -> Exception Filters
Exemplo de Trabalho
// auth.guard.ts
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from "@nestjs/common";
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const req = context.switchToHttp().getRequest();
const token = req.headers.authorization?.replace("Bearer ", "");
if (!token) throw new UnauthorizedException();
req.userId = "user-42";
return true;
}
}
// logging.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from "@nestjs/common";
import { Observable, tap } from "rxjs";
@Injectable()
export class LoggingInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
const start = Date.now();
const req = context.switchToHttp().getRequest();
return next.handle().pipe(
tap(() => console.log(`${req.method} ${req.url} ${Date.now() - start}ms`))
);
}
}
// roles.guard.ts
import { SetMetadata, Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
import { Reflector } from "@nestjs/core";
export const ROLES_KEY = "roles";
export const Roles = (...roles: string[]) => SetMetadata(ROLES_KEY, roles);
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const roles = this.reflector.get<string[]>(ROLES_KEY, context.getHandler());
if (!roles) return true;
const req = context.switchToHttp().getRequest();
return roles.includes(req.userRole);
}
}O que isso demonstra:
- Guard retorna
booleanou lança uma exceção para permitir/negar acesso - Interceptor envolve o handler com
pipedo RxJS para lógica de antes/depois SetMetadata+Reflectorpara verificações declarativas de roles- Guards e interceptors são injetáveis (DI funciona)
Mergulho Profundo
Como Funciona
| Componente | Executa quando | Propósito | Retorna |
|---|---|---|---|
| Pipe | Antes do handler | Transforma/valida a entrada | Valor transformado |
| Guard | Antes do handler | Autenticação/autorização | true ou lança exceção |
| Interceptor | Em torno do handler | Logging, caching, mapeamento | Fluxo Observable |
| Filter | Na exceção | Formatação da resposta de erro | Resposta HTTP |
Registro Global
// main.ts
app.useGlobalGuards(new AuthGuard());
app.useGlobalInterceptors(new LoggingInterceptor());
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));Pipes Embutidos
| Pipe | Propósito |
|---|---|
ValidationPipe | Validação de DTO com class-validator |
ParseIntPipe | Converte parâmetro string para inteiro |
ParseUUIDPipe | Valida formato UUID |
DefaultValuePipe | Valor padrão para parâmetros opcionais |
Armadilhas
- Guard após interceptor em mente, não no código - guards executam antes dos interceptors. Correção: coloque a autenticação em guards, não em interceptors.
ValidationPipesem decoradores DTO - a validação não faz nada. Correção: adicione decoradoresclass-validatoràs classes DTO.- Erros de Interceptor não capturados por filtro - erros RxJS precisam de
catchError. Correção: trate no interceptor ou deixe o filtro de exceção capturar. - Guard global bloqueia health check - Sondas K8s falham. Correção: decorador
@Public()com um guard que ignora rotas marcadas. - Guard em escopo de requisição em singleton - incompatibilidade de escopo. Correção: combine escopos ou use
Reflectorpara metadados. - Logging de PII em interceptor - registre apenas método/caminho/duração, não corpos.
Alternativas
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Express middleware | NestJS no Express, autenticação simples | Quer guards declarativos por rota |
| Fastify hooks | NestJS com adaptador Fastify | Precisa da DX dos decoradores Nest |
| Middleware no NestJS | Acesso bruto a request/response (cors) | Autenticação (guards são melhores) |
| Verificações manuais no controller | Protótipo rápido | Autenticação em produção |
FAQs
Guard vs middleware para autenticação?
Guards têm acesso ao contexto de execução (handler, metadados da classe) e integram-se com Reflector. Middleware é de nível mais baixo. Prefira guards para autenticação.
Interceptors podem modificar a resposta?
Sim. Use o operador map() para transformar o valor de retorno. Ou use tap() apenas para efeitos colaterais.
Como pular a autenticação para rotas específicas?
Crie um decorador de metadados @Public() e verifique-o no AuthGuard com Reflector.
Qual a diferença entre pipe e guard?
Pipes transformam/validam dados que entram no handler. Guards decidem se o handler deve ser executado.
Como adicionar timing de requisição globalmente?
LoggingInterceptor global com tap() medindo o tempo decorrido. Ou use um interceptor OpenTelemetry.
Pipes funcionam em gateways WebSocket?
Sim. NestJS suporta guards, pipes e interceptors em contextos WebSocket e RPC também.
Como `ValidationPipe` se compara ao Fastify JSON Schema?
ValidationPipe usa decoradores class-validator. Fastify usa JSON Schema. Sintaxe diferente, mesmo objetivo.
Posso usar múltiplos guards em uma rota?
Sim. @UseGuards(AuthGuard, RolesGuard) executa todos os guards na ordem. Todos devem retornar true.
Relacionados
- NestJS Basics - estrutura de módulos
- Dependency Injection - guards injetáveis
- Security Middleware - equivalente Express
- Middleware Pattern - conceito subjacente
- NestJS Best Practices - checklist da seção
Versões do Stack: Esta página foi escrita para Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, e NestJS 11.