NestJS中间件 #

什么是中间件? #

中间件是在路由处理程序之前执行的函数。中间件可以访问请求对象和响应对象,以及应用程序请求-响应周期中的下一个中间件函数。

中间件特点 #

  • 执行任何代码
  • 修改请求和响应对象
  • 结束请求-响应周期
  • 调用下一个中间件

创建中间件 #

类中间件 #

typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
    next();
  }
}

函数中间件 #

typescript
import { Request, Response, NextFunction } from 'express';

export function loggerMiddleware(
  req: Request,
  res: Response,
  next: NextFunction,
) {
  console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
  next();
}

应用中间件 #

在模块中配置 #

typescript
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { UsersController } from './users.controller';
import { LoggerMiddleware } from './logger.middleware';

@Module({
  controllers: [UsersController],
})
export class UsersModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('users');
  }
}

路由配置 #

typescript
consumer
  .apply(LoggerMiddleware)
  .forRoutes({ path: 'users', method: RequestMethod.GET });

多个路由 #

typescript
consumer
  .apply(LoggerMiddleware)
  .forRoutes('users', 'products');

排除路由 #

typescript
consumer
  .apply(LoggerMiddleware)
  .exclude(
    { path: 'users/health', method: RequestMethod.GET },
  )
  .forRoutes(UsersController);

多个中间件 #

typescript
consumer
  .apply(LoggerMiddleware, AuthMiddleware)
  .forRoutes('*');

全局中间件 #

使用实例方法 #

typescript
const app = await NestFactory.create(AppModule);
app.use(loggerMiddleware);
await app.listen(3000);

使用模块配置 #

typescript
@Module({
  imports: [],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(LoggerMiddleware)
      .forRoutes('*');
  }
}

中间件示例 #

日志中间件 #

typescript
import { Injectable, NestMiddleware, Logger } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class LoggingMiddleware implements NestMiddleware {
  private readonly logger = new Logger(LoggingMiddleware.name);

  use(req: Request, res: Response, next: NextFunction) {
    const { method, originalUrl, ip } = req;
    const startTime = Date.now();

    res.on('finish', () => {
      const { statusCode } = res;
      const duration = Date.now() - startTime;
      this.logger.log(
        `${method} ${originalUrl} ${statusCode} ${duration}ms - ${ip}`,
      );
    });

    next();
  }
}

认证中间件 #

typescript
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?.split(' ')[1];

    if (!token) {
      throw new UnauthorizedException('Token not found');
    }

    try {
      const decoded = this.verifyToken(token);
      req.user = decoded;
      next();
    } catch (error) {
      throw new UnauthorizedException('Invalid token');
    }
  }

  private verifyToken(token: string) {
    // Token verification logic
    return { id: 1, email: 'user@example.com' };
  }
}

CORS中间件 #

typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class CorsMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header(
      'Access-Control-Allow-Methods',
      'GET,HEAD,PUT,PATCH,POST,DELETE',
    );
    res.header(
      'Access-Control-Allow-Headers',
      'Content-Type, Authorization',
    );

    if (req.method === 'OPTIONS') {
      res.sendStatus(204);
      return;
    }

    next();
  }
}

请求限流中间件 #

typescript
import {
  Injectable,
  NestMiddleware,
  HttpException,
  HttpStatus,
} from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class RateLimitMiddleware implements NestMiddleware {
  private requests = new Map<string, number[]>();
  private readonly limit = 100;
  private readonly windowMs = 60000;

  use(req: Request, res: Response, next: NextFunction) {
    const ip = req.ip;
    const now = Date.now();

    if (!this.requests.has(ip)) {
      this.requests.set(ip, []);
    }

    const timestamps = this.requests.get(ip)!;
    const validTimestamps = timestamps.filter(t => now - t < this.windowMs);

    if (validTimestamps.length >= this.limit) {
      throw new HttpException(
        'Too many requests',
        HttpStatus.TOO_MANY_REQUESTS,
      );
    }

    validTimestamps.push(now);
    this.requests.set(ip, validTimestamps);

    next();
  }
}

请求体解析中间件 #

typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response, NextFunction } from 'express';

@Injectable()
export class BodyParserMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    let body = '';

    req.on('data', chunk => {
      body += chunk.toString();
    });

    req.on('end', () => {
      try {
        req.body = JSON.parse(body);
        next();
      } catch (error) {
        next(error);
      }
    });
  }
}

依赖注入 #

中间件支持依赖注入:

typescript
import { Injectable, NestMiddleware } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';

@Injectable()
export class ConfigMiddleware implements NestMiddleware {
  constructor(private configService: ConfigService) {}

  use(req: Request, res: Response, next: NextFunction) {
    const apiKey = this.configService.get('API_KEY');
    req.headers['x-api-key'] = apiKey;
    next();
  }
}

中间件执行顺序 #

text
请求 → 全局中间件 → 模块中间件 → 路由中间件 → 控制器 → 服务 → 响应

中间件最佳实践 #

1. 单一职责 #

每个中间件只做一件事:

typescript
// 日志中间件只负责日志
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    console.log(`${req.method} ${req.url}`);
    next();
  }
}

// 认证中间件只负责认证
@Injectable()
export class AuthMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    // 认证逻辑
    next();
  }
}

2. 错误处理 #

在中间件中正确处理错误:

typescript
@Injectable()
export class ErrorHandlingMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    try {
      next();
    } catch (error) {
      next(error);
    }
  }
}

3. 异步操作 #

处理异步操作:

typescript
@Injectable()
export class AsyncMiddleware implements NestMiddleware {
  async use(req: Request, res: Response, next: NextFunction) {
    await this.doSomethingAsync();
    next();
  }

  private async doSomethingAsync() {
    return new Promise(resolve => setTimeout(resolve, 100));
  }
}

总结 #

本章学习了NestJS中间件:

  • 中间件的概念和特点
  • 类中间件和函数中间件
  • 中间件的应用方式
  • 常用中间件示例
  • 中间件最佳实践

接下来,让我们学习 管道(Pipe)

最后更新:2026-03-28