11. 中间件:Nest.js 的请求和响应处理工具

344 阅读5分钟

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);
  }
}

在这个例子中,我们使用 MiddlewareConsumerLoggingMiddleware 应用到 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);
  }
}

在这个例子中,我们使用 MiddlewareConsumerLoggingMiddlewareAuthMiddleware 应用到 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);
  }
}

在这个例子中,我们使用 MiddlewareConsumerLoggingMiddlewareAuthMiddlewareCustomMiddleware 应用到 BooksController 的所有路由。每次请求到达 BooksController 的方法之前,都会经过这三个中间件。

结论

在这篇文章中,我们深入探讨了 Nest.js 中的中间件,并通过实际例子展示了如何创建和使用中间件。我们还学习了如何将中间件应用到特定的控制器或全局范围内,以及如何使用中间件进行日志记录、身份验证和请求修改。

中间件是处理请求和响应的强大工具,可以在请求到达控制器之前或响应发送到客户端之前执行一些操作。通过使用中间件,我们可以实现日志记录、身份验证、请求修改等功能,使应用更加灵活和高效。

感谢你的阅读!如果你有任何问题或建议,欢迎在评论区留言。我们下次再见!

预告

在下一篇文章中,我们将探讨 Nest.js 中的 GraphQL 支持。GraphQL 是一种用于 API 的查询语言,可以让客户端灵活地请求数据。敬请期待!