Explicación detallada de Guards, Interceptors y Filters en NestJS
- 1232Palabras
- 6Minutos
- 11 Jul, 2024
NestJS ofrece muchas herramientas y características poderosas para gestionar y manejar solicitudes. En este artículo, exploraremos en profundidad los Guards, Interceptors y Filters en NestJS, y mostraremos ejemplos de su uso en aplicaciones reales. También explicaremos la diferencia entre estos y los Middleware.
Guards
Concepto de Guards
Los Guards son un mecanismo utilizado para controlar el flujo de solicitudes, permitiendo validaciones y verificaciones antes de que la solicitud llegue al controlador. Generalmente se utilizan para implementar lógica de autenticación y autorización.
Creación de un Guard
Para crear un Guard, es necesario implementar la interfaz CanActivate
y definir el método canActivate
. A continuación se muestra un ejemplo simple de un Guard de autenticación:
1import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";2import { Observable } from "rxjs";3
4@Injectable()5export class AuthGuard implements CanActivate {6 canActivate(7 context: ExecutionContext,8 ): boolean | Promise<boolean> | Observable<boolean> {9 const request = context.switchToHttp().getRequest();10 return this.validateRequest(request);11 }12
13 validateRequest(request: any): boolean {14 // Lógica de validación15 return request.headers.authorization === "my-secret-token"; // Ejemplo simple16 }17}
Aplicación de Guards
Los Guards se pueden aplicar a nivel de controlador o de método, utilizando el decorador @UseGuards
:
Nivel de controlador
1import { Controller, Get, UseGuards } from "@nestjs/common";2import { AuthGuard } from "./auth.guard";3
4@Controller("cats")5@UseGuards(AuthGuard)6export class CatsController {7 @Get()8 findAll() {9 return "This action returns all cats";10 }11}
Nivel de método
1import { Controller, Get, UseGuards } from "@nestjs.common";2import { AuthGuard } from "./auth.guard";3
4@Controller("cats")5export class CatsController {6 @Get()7 @UseGuards(AuthGuard)8 findAll() {9 return "This action returns all cats";10 }11}
Nivel global
1import { NestFactory } from "@nestjs/core";2import { AppModule } from "./app.module";3import { AuthGuard } from "./auth.guard";4
5async function bootstrap() {6 const app = await NestFactory.create(AppModule);7 app.useGlobalGuards(new AuthGuard());8 await app.listen(3000);9}10bootstrap();
Casos de uso de Guards
Los Guards se utilizan a menudo para proteger rutas que requieren autenticación o autorización. Por ejemplo, en una ruta que requiere que el usuario haya iniciado sesión, se puede usar un Guard para verificar la identidad del usuario.
Interceptors
Concepto de Interceptors
Los Interceptors son un mecanismo que permite ejecutar lógica personalizada antes y después de procesar una solicitud. Se utilizan comúnmente para el registro de logs, la transformación de datos de respuesta y el manejo de excepciones.
Creación de un Interceptor
Para crear un Interceptor, es necesario implementar la interfaz NestInterceptor
y definir el método intercept
. A continuación se muestra un ejemplo de un Interceptor que formatea los datos de respuesta:
1import {2 Injectable,3 NestInterceptor,4 ExecutionContext,5 CallHandler,6} from "@nestjs/common";7import { Observable } from "rxjs";8import { map } from "rxjs/operators";9
10@Injectable()11export class TransformInterceptor implements NestInterceptor {12 intercept(context: ExecutionContext, next: CallHandler): Observable<any> {13 return next.handle().pipe(map((data) => ({ data })));14 }15}
Aplicación de Interceptors
Los Interceptors se pueden aplicar a nivel de controlador o de método, utilizando el decorador @UseInterceptors
:
Nivel de controlador
1import { Controller, Get, UseInterceptors } from "@nestjs/common";2import { TransformInterceptor } from "./transform.interceptor";3
4@Controller("cats")5@UseInterceptors(TransformInterceptor)6export class CatsController {7 @Get()8 findAll() {9 return [{ name: "Tom" }, { name: "Jerry" }];10 }11}
Nivel de método
1import { Controller, Get, UseInterceptors } from "@nestjs.common";2import { TransformInterceptor } from "./transform.interceptor";3
4@Controller("cats")5export class CatsController {6 @Get()7 @UseInterceptors(TransformInterceptor)8 findAll() {9 return [{ name: "Tom" }, { name: "Jerry" }];10 }11}
Nivel global
1import { NestFactory } from "@nestjs/core";2import { AppModule } from "./app.module";3import { TransformInterceptor } from "./transform.interceptor";4
5async function bootstrap() {6 const app = await NestFactory.create(AppModule);7 app.useGlobalInterceptors(new TransformInterceptor());8 await app.listen(3000);9}10bootstrap();
Casos de uso de Interceptors
Los Interceptors se utilizan comúnmente para el registro de logs, la transformación de datos de respuesta y el manejo de excepciones. Por ejemplo, en una ruta que requiere que los datos de respuesta tengan un formato específico, se puede usar un Interceptor para transformar los datos.
Filters
Concepto de Filters
Los Filters son un mecanismo utilizado para capturar y manejar excepciones no gestionadas. Pueden capturar cualquier excepción no gestionada en un controlador y ejecutar lógica de manejo de errores personalizada.
Creación de un Filter
Para crear un Filter, es necesario implementar la interfaz ExceptionFilter
y definir el método catch
. A continuación se muestra un ejemplo de un Filter de excepciones global:
1import {2 ExceptionFilter,3 Catch,4 ArgumentsHost,5 HttpException,6} from "@nestjs/common";7import { Request, Response } from "express";8
9@Catch(HttpException)10export class HttpExceptionFilter implements ExceptionFilter {11 catch(exception: HttpException, host: ArgumentsHost) {12 const ctx = host.switchToHttp();13 const response = ctx.getResponse<Response>();14 const request = ctx.getRequest<Request>();15 const status = exception.getStatus();16
17 response.status(status).json({18 statusCode: status,19 timestamp: new Date().toISOString(),20 path: request.url,21 });22 }23}
Aplicación de Filters
Los Filters se pueden aplicar a nivel de controlador o de método, utilizando el decorador @UseFilters
, o se pueden aplicar globalmente:
Nivel de controlador
1import { Controller, Get, UseFilters } from "@nestjs.common";2import { HttpExceptionFilter } from "./http-exception.filter";3
4@Controller("cats")5@UseFilters(HttpExceptionFilter)6export class CatsController {7 @Get()8 findAll() {9 throw new HttpException("Forbidden", 403);10 }11}
Nivel de método
1import { Controller, Get, UseFilters } from "@nestjs.common";2import { HttpExceptionFilter } from "./http-exception.filter";3
4@Controller("cats")5export class CatsController {6 @Get()7 @UseFilters(HttpExceptionFilter)8 findAll() {9 throw new HttpException("Forbidden", 403);10 }11}
Nivel global
1import { NestFactory } from "@nestjs/core";2import { AppModule } from "./app.module";3import { HttpExceptionFilter } from "./http-exception.filter";4
5async function bootstrap() {6 const app = await NestFactory.create(AppModule);7 app.useGlobalFilters(new HttpExceptionFilter());8 await app.listen(3000);9}10bootstrap();
Casos de uso de Filters
Los Filters se utilizan comúnmente para el manejo global de errores. Por ejemplo, se puede crear un Filter de excepciones global para manejar todas las excepciones no gestionadas y devolver respuestas de error coherentes.
Middleware
Concepto de Middleware
El Middleware es una función que se ejecuta antes de que la solicitud llegue al manejador de rutas y antes de que la respuesta se envíe al cliente. El Middleware se puede utilizar para manejar solicitudes, modificar respuestas, terminar el ciclo de solicitud-respuesta o llamar a la siguiente función de Middleware.
Creación de Middleware
Para crear un Middleware, es necesario implementar la interfaz NestMiddleware
y definir el método use
. A continuación se muestra un ejemplo simple de un Middleware de registro de logs:
1import { Injectable, NestMiddleware } from "@nestjs.common";2import { Request, Response, NextFunction } from "express";3
4@Injectable()5export class LoggerMiddleware implements NestMiddleware {6 use(req: Request, res: Response, next: NextFunction) {7 console.log(`Request...`);8 next();9 }10}
Aplicación de Middleware
El Middleware se puede aplicar en el módulo utilizando el método forRoutes
:
1import { Module, NestModule, MiddlewareConsumer } from "@nestjs.common";2import { CatsController } from "./cats.controller";3import { LoggerMiddleware } from "./logger.middleware";4
5@Module({6 controllers: [CatsController],7})8export class CatsModule implements NestModule {9 configure(consumer: MiddlewareConsumer) {10 consumer.apply(LoggerMiddleware).forRoutes(CatsController);11 }12}
Casos de uso de Middleware
El Middleware se utiliza comúnmente para el registro de logs, la validación de solicitudes y la compresión de respuestas. Por ejemplo, en un módulo que requiere registro de logs para todas las solicitudes, se puede usar Middleware para registrar la información de la solicitud.
Diferencias entre Guards, Interceptors, Filters y Middleware
- Guards (Guardias): Utilizados para controlar si una solicitud puede continuar, comúnmente usados para autenticación y autorización.
- Interceptors (Interceptores): Utilizados para ejecutar lógica adicional antes y después de una solicitud, comúnmente usados para registro de logs, transformación de datos de respuesta y manejo de excepciones.
- Filters (Filtros): Utilizados para capturar y manejar excepciones no gestionadas, comúnmente usados para manejo global de errores.
- Middleware: Funciones que se ejecutan antes de que la solicitud llegue al manejador de rutas y antes de que la respuesta se envíe al cliente, comúnmente usados para registro de logs, validación de solicitudes y manipulación de respuestas.
Conclusión
Este artículo proporcionó una explicación detallada de Guards, Interceptors, Filters y Middleware en NestJS, junto con ejemplos que demuestran sus casos de uso en aplicaciones reales. Al utilizar estas herramientas de manera efectiva, podemos construir aplicaciones NestJS potentes y flexibles. También discutimos las diferencias entre estas herramientas para ayudar a comprender mejor sus aplicaciones.