TL;DR
- Middleware = runs before route handler (like Express). Good for logging, CORS.
- Guards = determine if request proceeds. Return
true/false. Good for auth.
- Execution order: Middleware → Guards → Interceptors → Pipes → Handler.
Guards
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
const token = request.headers.authorization?.replace('Bearer ', '');
if (!token) return false;
// validate token...
return true;
}
}
// Apply to controller/route
@UseGuards(AuthGuard)
@Controller('users')
export class UsersController { /* ... */ }
// Apply globally
app.useGlobalGuards(new AuthGuard());
Middleware
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`${req.method} ${req.url}`);
next();
}
}
// Register in module
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('*');
}
}
Execution Order
Request
→ Middleware
→ Guards
→ Interceptors (before)
→ Pipes
→ Route Handler
→ Interceptors (after)
→ Response
Common Patterns
| Need |
Solution |
| Auth check |
Guard + JWT strategy |
| Role-based access |
Guard + custom decorator @Roles('admin') |
| Request logging |
Middleware |
| Response transform |
Interceptor |
| Input validation |
Pipe + class-validator |