11. 中间件:Nest.js 的请求和响应处理工具
介绍
欢迎回来!在前几篇文章中,我们已经了解了如何创建控制器、服务、中间件、管道、异常过滤器、守卫、拦截器和模块,并使用它们来处理 HTTP 请求。在这篇文章中,我们将探讨 Nest.js 中的中间件(Middleware)。中间件是处理请求和响应的强大工具,可以在请求到达控制器之前或响应发送到客户端之前执行一些操作。让我们一起深入了解中间件的工作原理和使用方法。
什么是中间件?
中间件是一个函数,它在请求到达路由处理器之前或响应发送到客户端之前执行。中间件可以用于执行各种任务,如日志记录、身份验证、请求修改和响应修改等。中间件在 Express.js 和 Koa.js 等框架中非常常见,Nest.js 也支持使用中间件。
创建一个中间件
让我们通过一个实际例子来了解如何创建和使用中间件。假设我们要创建一个日志中间件,用于记录每个请求的详细信息。
首先,使用 Nest CLI 创建一个新的中间件:
nest generate middleware logging
这条命令会在 src 目录下生成一个 logging.middleware.ts 文件。让我们看看这个文件的内容:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class LoggingMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`Request...`);
next();
}
}
@Injectable():将类标记为可注入的服务。use方法:中间件的核心方法,接收请求对象、响应对象和下一个中间件函数。
使用中间件进行日志记录
在这个例子中,我们在每个请求到达路由处理器之前记录 "Request..."。让我们将 LoggingMiddleware 应用到 BooksController 的所有路由。
打开 books.module.ts 文件,修改如下:
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { BooksController } from './books.controller';
import { BooksService } from './books.service';
import { LoggingMiddleware } from './logging.middleware';
@Module({
controllers: [BooksController],
providers: [BooksService],
})
export class BooksModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggingMiddleware)
.forRoutes(BooksController);
}
}
在这个例子中,我们使用 MiddlewareConsumer 将 LoggingMiddleware 应用到 BooksController 的所有路由。每次请求到达 BooksController 的方法之前,都会经过 LoggingMiddleware。
全局中间件
如果你希望中间件应用于所有路由,可以将其注册为全局中间件。打开 main.ts 文件,修改如下:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { LoggingMiddleware } from './logging.middleware';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(new LoggingMiddleware().use);
await app.listen(3000);
}
bootstrap();
在这个例子中,我们使用 app.use 方法将 LoggingMiddleware 注册为全局中间件。这样,所有的请求都会经过 LoggingMiddleware。
身份验证中间件
中间件还可以用于身份验证。让我们创建一个新的中间件,用于验证请求中的令牌。
首先,使用 Nest CLI 创建一个新的中间件:
nest generate middleware auth
然后,修改 auth.middleware.ts 文件如下:
import { Injectable, NestMiddleware, UnauthorizedException } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class AuthMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
const token = req.headers['authorization'];
if (!token || token !== 'valid-token') {
throw new UnauthorizedException('Invalid token');
}
next();
}
}
在这个例子中,我们从请求头中获取令牌,并验证其是否有效。如果令牌无效,我们抛出一个 UnauthorizedException 异常;否则,我们调用 next 函数继续处理请求。
要使用这个身份验证中间件,我们可以将其应用到特定的控制器或全局范围内。让我们将 AuthMiddleware 应用到 BooksController。
打开 books.module.ts 文件,修改如下:
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { BooksController } from './books.controller';
import { BooksService } from './books.service';
import { LoggingMiddleware } from './logging.middleware';
import { AuthMiddleware } from './auth.middleware';
@Module({
controllers: [BooksController],
providers: [BooksService],
})
export class BooksModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggingMiddleware, AuthMiddleware)
.forRoutes(BooksController);
}
}
在这个例子中,我们使用 MiddlewareConsumer 将 LoggingMiddleware 和 AuthMiddleware 应用到 BooksController 的所有路由。每次请求到达 BooksController 的方法之前,都会经过这两个中间件。
请求修改中间件
中间件还可以用于修改请求对象。让我们创建一个新的中间件,用于在请求对象中添加一个自定义属性。
首先,使用 Nest CLI 创建一个新的中间件:
nest generate middleware custom
然后,修改 custom.middleware.ts 文件如下:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';
@Injectable()
export class CustomMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
req['customProperty'] = 'customValue';
next();
}
}
在这个例子中,我们在请求对象中添加了一个名为 customProperty 的自定义属性,并将其值设置为 customValue。
要使用这个请求修改中间件,我们可以将其应用到特定的控制器或全局范围内。让我们将 CustomMiddleware 应用到 BooksController。
打开 books.module.ts 文件,修改如下:
import { Module, MiddlewareConsumer, RequestMethod } from '@nestjs/common';
import { BooksController } from './books.controller';
import { BooksService } from './books.service';
import { LoggingMiddleware } from './logging.middleware';
import { AuthMiddleware } from './auth.middleware';
import { CustomMiddleware } from './custom.middleware';
@Module({
controllers: [BooksController],
providers: [BooksService],
})
export class BooksModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggingMiddleware, AuthMiddleware, CustomMiddleware)
.forRoutes(BooksController);
}
}
在这个例子中,我们使用 MiddlewareConsumer 将 LoggingMiddleware、AuthMiddleware 和 CustomMiddleware 应用到 BooksController 的所有路由。每次请求到达 BooksController 的方法之前,都会经过这三个中间件。
结论
在这篇文章中,我们深入探讨了 Nest.js 中的中间件,并通过实际例子展示了如何创建和使用中间件。我们还学习了如何将中间件应用到特定的控制器或全局范围内,以及如何使用中间件进行日志记录、身份验证和请求修改。
中间件是处理请求和响应的强大工具,可以在请求到达控制器之前或响应发送到客户端之前执行一些操作。通过使用中间件,我们可以实现日志记录、身份验证、请求修改等功能,使应用更加灵活和高效。
感谢你的阅读!如果你有任何问题或建议,欢迎在评论区留言。我们下次再见!
预告
在下一篇文章中,我们将探讨 Nest.js 中的 GraphQL 支持。GraphQL 是一种用于 API 的查询语言,可以让客户端灵活地请求数据。敬请期待!