深入讲解NestJS中的守卫、拦截器和过滤器

NestJS提供了许多强大的工具和功能来管理和处理请求。在本文中,我们将深入探讨 NestJS 中的守卫(Guards)、拦截器(Interceptors)和过滤器(Filters),并通过实际应用中的示例说明它们的使用场景。同时,我们还将通过案例说明它们与中间件的区别。

守卫(Guards)

守卫的概念

守卫是一种用于控制请求流的机制,可以在请求到达处理器之前进行验证和检查。它们通常用于实现认证和授权逻辑。

创建守卫

要创建一个守卫,需要实现 CanActivate 接口,并定义 canActivate 方法。以下是一个简单的认证守卫示例:

1
import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
2
import { Observable } from "rxjs";
3
4
@Injectable()
5
export 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
// 验证逻辑
15
return request.headers.authorization === "my-secret-token"; // 简单的示例
16
}
17
}

应用守卫

守卫可以在控制器或方法级别应用,使用 @UseGuards 装饰器:

控制器级别
1
import { Controller, Get, UseGuards } from "@nestjs/common";
2
import { AuthGuard } from "./auth.guard";
3
4
@Controller("cats")
5
@UseGuards(AuthGuard)
6
export class CatsController {
7
@Get()
8
findAll() {
9
return "This action returns all cats";
10
}
11
}
方法级别
1
import { Controller, Get, UseGuards } from "@nestjs/common";
2
import { AuthGuard } from "./auth.guard";
3
4
@Controller("cats")
5
export class CatsController {
6
@Get()
7
@UseGuards(AuthGuard)
8
findAll() {
9
return "This action returns all cats";
10
}
11
}
全局级别
1
import { NestFactory } from "@nestjs/core";
2
import { AppModule } from "./app.module";
3
import { AuthGuard } from "./auth.guard";
4
5
async function bootstrap() {
6
const app = await NestFactory.create(AppModule);
7
app.useGlobalGuards(new AuthGuard());
8
await app.listen(3000);
9
}
10
bootstrap();

守卫的实际应用场景

守卫常用于保护需要认证或授权的路由。例如,在一个需要用户登录才能访问的路由中,可以使用守卫来验证用户身份。

拦截器(Interceptors)

拦截器的概念

拦截器是一种可以在处理请求之前和之后执行自定义逻辑的机制。它们常用于日志记录、变换响应数据和异常处理等。

创建拦截器

要创建一个拦截器,需要实现 NestInterceptor 接口,并定义 intercept 方法。以下是一个响应数据格式化的拦截器示例:

1
import {
2
Injectable,
3
NestInterceptor,
4
ExecutionContext,
5
CallHandler,
6
} from "@nestjs/common";
7
import { Observable } from "rxjs";
8
import { map } from "rxjs/operators";
9
10
@Injectable()
11
export class TransformInterceptor implements NestInterceptor {
12
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
13
return next.handle().pipe(map((data) => ({ data })));
14
}
15
}

应用拦截器

拦截器可以在控制器或方法级别应用,使用 @UseInterceptors 装饰器:

控制器级别
1
import { Controller, Get, UseInterceptors } from "@nestjs/common";
2
import { TransformInterceptor } from "./transform.interceptor";
3
4
@Controller("cats")
5
@UseInterceptors(TransformInterceptor)
6
export class CatsController {
7
@Get()
8
findAll() {
9
return [{ name: "Tom" }, { name: "Jerry" }];
10
}
11
}
方法级别
1
import { Controller, Get, UseInterceptors } from "@nestjs/common";
2
import { TransformInterceptor } from "./transform.interceptor";
3
4
@Controller("cats")
5
export class CatsController {
6
@Get()
7
@UseInterceptors(TransformInterceptor)
8
findAll() {
9
return [{ name: "Tom" }, { name: "Jerry" }];
10
}
11
}
全局级别
1
import { NestFactory } from "@nestjs/core";
2
import { AppModule } from "./app.module";
3
import { TransformInterceptor } from "./transform.interceptor";
4
5
async function bootstrap() {
6
const app = await NestFactory.create(AppModule);
7
app.useGlobalInterceptors(new TransformInterceptor());
8
await app.listen(3000);
9
}
10
bootstrap();

拦截器的实际应用场景

拦截器常用于日志记录、响应数据转换和异常处理。例如,在一个需要对响应数据进行统一格式化的路由中,可以使用拦截器来变换数据。

过滤器(Filters)

过滤器的概念

过滤器是一种用于捕获和处理未处理异常的机制。它们可以捕获控制器中的任何未处理异常,并执行自定义的错误处理逻辑。

创建过滤器

要创建一个过滤器,需要实现 ExceptionFilter 接口,并定义 catch 方法。以下是一个全局异常过滤器示例:

1
import {
2
ExceptionFilter,
3
Catch,
4
ArgumentsHost,
5
HttpException,
6
} from "@nestjs/common";
7
import { Request, Response } from "express";
8
9
@Catch(HttpException)
10
export 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
}

应用过滤器

过滤器可以在控制器或方法级别应用,使用 @UseFilters 装饰器,也可以全局应用:

控制器级别
1
import { Controller, Get, UseFilters } from "@nestjs/common";
2
import { HttpExceptionFilter } from "./http-exception.filter";
3
4
@Controller("cats")
5
@UseFilters(HttpExceptionFilter)
6
export class CatsController {
7
@Get()
8
findAll() {
9
throw new HttpException("Forbidden", 403);
10
}
11
}
方法级别
1
import { Controller, Get, UseFilters } from "@nestjs/common";
2
import { HttpExceptionFilter } from "./http-exception.filter";
3
4
@Controller("cats")
5
export class CatsController {
6
@Get()
7
@UseFilters(HttpExceptionFilter)
8
findAll() {
9
throw new HttpException("Forbidden", 403);
10
}
11
}
全局级别
1
import { NestFactory } from "@nestjs/core";
2
import { AppModule } from "./app.module";
3
import { HttpExceptionFilter } from "./http-exception.filter";
4
5
async function bootstrap() {
6
const app = await NestFactory.create(AppModule);
7
app.useGlobalFilters(new HttpExceptionFilter());
8
await app.listen(3000);
9
}
10
bootstrap();

过滤器的实际应用场景

过滤器常用于全局错误处理。例如,可以创建一个全局异常过滤器来统一处理所有未处理的异常,并返回一致的错误响应。

中间件(Middleware)

中间件的概念

中间件是一种用于在请求到达路由处理器之前和响应发送到客户端之前执行的函数。中间件可以用于处理请求、修改响应、终止请求-响应周期或调用下一个中间件函数。

创建中间件

要创建一个中间件,需要实现 NestMiddleware 接口,并定义 use 方法。以下是一个简单的日志记录中间件示例:

1
import { Injectable, NestMiddleware } from "@nestjs/common";
2
import { Request, Response, NextFunction } from "express";
3
4
@Injectable()
5
export class LoggerMiddleware implements NestMiddleware {
6
use(req: Request, res: Response, next: NextFunction) {
7
console.log(`Request...`);
8
next();
9
}
10
}

应用中间件

中间件可以在模块中应用,使用 forRoutes 方法:

1
import { Module, NestModule, MiddlewareConsumer } from "@nestjs/common";
2
import { CatsController } from "./cats.controller";
3
import { LoggerMiddleware } from "./logger.middleware";
4
5
@Module({
6
controllers: [CatsController],
7
})
8
export class CatsModule implements NestModule {
9
configure(consumer: MiddlewareConsumer) {
10
consumer.apply(LoggerMiddleware).forRoutes(CatsController);
11
}
12
}

中间件的实际应用场景

中间件常用于日志记录、请求验证、响应压缩等。例如,在一个需要对所有请求进行日志记录的模块中,可以使用中间件来记录请求信息。

守卫、拦截器、过滤器和中间件的区别

  • 守卫(Guards):用于控制请求是否可以继续执行,常用于认证和授权。
  • 拦截器(Interceptors):用于在请求前后执行额外逻辑,常用于日志记录、响应数据转换和异常处理。
  • 过滤器(Filters):用于捕获和处理未处理异常,常用于全局错误处理。
  • 中间件(Middleware):用于在请求到达路由处理器之前和响应发送到客户端之前执行额外逻辑,常用于日志记录、请求验证和响应压缩。

总结

本文深入探讨了 NestJS 中的守卫、拦截器、过滤器和中间件,并通过实例说明了它们在实际应用中的使用场景。通过合理使用这些工具,我们可以构建出功能强大且灵活的 NestJS 应用。同时,我们还讨论了它们之间的区别,帮助大家更好地理解这些工具的应用场景。

美团外卖红包 饿了么红包 支付宝红包