中间件系统.md 24 KB

中间件系统

本文引用的文件

  • server/src/app.ts
  • server/src/middleware/auth.ts
  • server/src/middleware/errorHandler.ts
  • server/src/middleware/security.ts
  • server/src/middleware/rate-limiter.ts
  • server/src/middleware/performance.ts
  • server/src/middleware/cache.ts
  • server/src/middleware/usageLimit.ts
  • server/src/types/index.ts
  • server/src/modules/auth/auth.controller.ts
  • server/src/modules/book-generator/langgraph-controller.ts

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考量
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向“AI有声书生成平台”的后端中间件体系,围绕 Koa.js 中间件的设计与实现进行系统化梳理,重点覆盖以下方面:

  • 中间件执行顺序与上下文传递机制
  • 错误处理与统一异常模型
  • 安全中间件的防护策略(XSS、SQL 注入、敏感数据脱敏)
  • 限流中间件的流量控制策略与 Redis/内存回退
  • 性能中间件的监控指标与慢请求告警
  • 缓存中间件的命中与失效策略
  • 使用次数与字数限额中间件的配额校验
  • 中间件配置参数、自定义中间件开发指南与最佳实践
  • 实际代码示例路径与调试方法

项目结构

中间件系统位于 server/src/middleware 目录,并在应用入口 server/src/app.ts 中集中注册。各中间件模块职责清晰、边界明确,通过 Koa 的洋葱模型串联,形成完整的请求生命周期。

graph TB
A["应用入口<br/>server/src/app.ts"] --> B["错误处理中间件<br/>errorHandler.ts"]
A --> C["Sentry 错误监控<br/>app.ts 内部调用"]
A --> D["性能监控中间件<br/>performance.ts"]
A --> E["HTTP 日志中间件<br/>app.ts 引入"]
A --> F["XSS 防护中间件<br/>security.ts"]
A --> G["SQL 注入防护中间件<br/>security.ts"]
A --> H["CORS 中间件<br/>app.ts"]
A --> I["Body/静态文件/上传中间件<br/>app.ts"]
A --> J["路由注册<br/>app.ts"]
J --> K["认证中间件必需<br/>auth.ts"]
J --> L["可选认证中间件<br/>auth.ts"]
J --> M["使用次数/字数限额中间件<br/>usageLimit.ts"]
J --> N["限流中间件按场景<br/>rate-limiter.ts"]
J --> O["缓存中间件按场景<br/>cache.ts"]

图表来源

  • server/src/app.ts:63-130
  • server/src/middleware/auth.ts:7-49
  • server/src/middleware/security.ts:6-27
  • server/src/middleware/performance.ts:29-76
  • server/src/middleware/errorHandler.ts:3-24
  • server/src/middleware/rate-limiter.ts:49-120
  • server/src/middleware/cache.ts:13-48
  • server/src/middleware/usageLimit.ts:7-49

章节来源

  • server/src/app.ts:63-130

核心组件

  • 错误处理中间件:统一捕获异常,输出标准化响应,并在开发环境输出堆栈;提供多种业务错误类型。
  • 安全中间件:XSS 防护、SQL 注入检测、敏感数据脱敏;设置安全响应头。
  • 限流中间件:支持 Redis/内存双栈,内置多场景限流器(API、登录、短信、TTS、上传)。
  • 性能中间件:统计总请求数、平均响应时间、慢请求、错误率与端点级指标。
  • 缓存中间件:基于 Redis 的读写缓存与批量清空,支持自定义键生成器。
  • 使用次数/字数限额中间件:基于用户会员等级的配额校验与状态注入。
  • 认证中间件:基于 JWT 的强认证与可选认证(自动注入测试用户)。

章节来源

  • server/src/middleware/errorHandler.ts:3-67
  • server/src/middleware/security.ts:6-154
  • server/src/middleware/rate-limiter.ts:1-120
  • server/src/middleware/performance.ts:1-110
  • server/src/middleware/cache.ts:1-98
  • server/src/middleware/usageLimit.ts:1-66
  • server/src/middleware/auth.ts:1-81

架构总览

下图展示了请求在中间件链中的流转与关键节点:

sequenceDiagram
participant Client as "客户端"
participant App as "Koa 应用<br/>app.ts"
participant EH as "错误处理<br/>errorHandler.ts"
participant Perf as "性能监控<br/>performance.ts"
participant Sec as "安全中间件<br/>security.ts"
participant CORS as "CORS<br/>app.ts"
participant Body as "Body/静态/上传<br/>app.ts"
participant Route as "路由<br/>app.ts"
participant Auth as "认证中间件<br/>auth.ts"
participant Limit as "使用次数/字数限额<br/>usageLimit.ts"
participant RL as "限流中间件<br/>rate-limiter.ts"
participant Cache as "缓存中间件<br/>cache.ts"
participant Ctrl as "控制器<br/>auth.controller.ts"
Client->>App : "HTTP 请求"
App->>EH : "进入错误处理"
EH->>Perf : "进入性能监控"
Perf->>Sec : "进入安全中间件"
Sec->>CORS : "进入 CORS"
CORS->>Body : "进入 Body/静态/上传"
Body->>Route : "进入路由"
Route->>Auth : "进入认证中间件"
Auth->>Limit : "进入使用次数/字数限额"
Limit->>RL : "进入限流中间件"
RL->>Cache : "进入缓存中间件"
Cache->>Ctrl : "进入控制器"
Ctrl-->>Client : "响应"
Note over EH,Perf : "异常在 EH 中统一捕获并格式化"
Note over Perf,Cache : "性能指标在 Perf 中统计"

图表来源

  • server/src/app.ts:63-130
  • server/src/middleware/errorHandler.ts:3-24
  • server/src/middleware/performance.ts:29-76
  • server/src/middleware/security.ts:6-27
  • server/src/middleware/auth.ts:7-49
  • server/src/middleware/usageLimit.ts:7-49
  • server/src/middleware/rate-limiter.ts:49-120
  • server/src/middleware/cache.ts:13-48
  • server/src/modules/auth/auth.controller.ts:54-64

详细组件分析

认证中间件(JWT)

  • 设计要点
    • 强制认证:要求 Authorization 头且格式为 Bearer Token,使用固定密钥验证;开发模式可通过开关跳过。
    • 可选认证:若携带有效 Token 则注入用户信息,否则注入测试用户(超级 VIP)。
    • 上下文传递:将用户信息注入 ctx.state.user,后续中间件可读取。
  • 执行顺序
    • 在路由注册之前安装,确保所有受保护路由均经过认证。
  • 错误处理
    • 缺失头、格式错误、过期或无效 Token 均抛出统一未授权错误。
  • 实际使用示例

    • 受保护路由示例:server/src/modules/auth/auth.controller.ts:54-64
    • 可选认证路由示例:server/src/modules/book-generator/langgraph-controller.ts:519-573

      flowchart TD
      Start(["进入 authMiddleware"]) --> DevCheck{"开发模式启用?"}
      DevCheck --> |是| InjectTest["注入测试用户<br/>ctx.state.user"]
      InjectTest --> Next1["调用 next()"]
      DevCheck --> |否| HasHeader{"存在 Authorization 头?"}
      HasHeader --> |否| ThrowMissing["抛出未授权错误"]
      HasHeader --> |是| ParseHeader["解析 Bearer Token"]
      ParseHeader --> Verify["验证 JWT"]
      Verify --> |成功| InjectUser["注入用户信息<br/>ctx.state.user"]
      InjectUser --> Next2["调用 next()"]
      Verify --> |失败| ThrowErr["抛出未授权或应用错误"]
      Next1 --> End(["结束"])
      Next2 --> End
      ThrowMissing --> End
      ThrowErr --> End
      

图表来源

  • server/src/middleware/auth.ts:7-49

章节来源

  • server/src/middleware/auth.ts:1-81
  • server/src/modules/auth/auth.controller.ts:54-64
  • server/src/modules/book-generator/langgraph-controller.ts:519-573

错误处理中间件(统一异常捕获)

  • 设计要点
    • 包裹整个中间件链,捕获任意同步/异步错误。
    • 统一响应结构:code、message、data;开发环境附加 stack。
    • 提供多种业务错误类型:未授权、禁止访问、资源不存在、请求错误、配额超限等。
  • 执行顺序
    • 最外层安装,确保所有错误被拦截与格式化。
  • 实际使用示例

    • 控制器内主动抛错示例:server/src/modules/auth/auth.controller.ts:14-16

      flowchart TD
      Enter(["进入 errorHandler"]) --> TryNext["尝试执行下游中间件/路由"]
      TryNext --> |正常| Exit(["结束"])
      TryNext --> |异常| Catch["捕获错误"]
      Catch --> SetResp["设置状态码与响应体"]
      SetResp --> DevEnv{"开发环境?"}
      DevEnv --> |是| AddStack["附加堆栈信息"]
      DevEnv --> |否| SkipStack["不附加堆栈"]
      AddStack --> Exit
      SkipStack --> Exit
      

图表来源

  • server/src/middleware/errorHandler.ts:3-24

章节来源

  • server/src/middleware/errorHandler.ts:1-67
  • server/src/modules/auth/auth.controller.ts:14-16

安全中间件(XSS/SQL 注入/敏感数据脱敏)

  • 设计要点
    • XSS 防护:递归清洗请求体与查询参数中的危险字符与脚本标签,设置安全响应头。
    • SQL 注入检测:对查询参数与请求体进行正则扫描,命中即拒绝。
    • 敏感数据脱敏:对响应体中常见敏感字段进行掩码处理。
  • 执行顺序
    • 在路由之前安装,保证所有请求与响应均经过安全处理。
  • 实际使用示例

    • XSS 防护中间件:server/src/middleware/security.ts:6-27
    • SQL 注入防护中间件:server/src/middleware/security.ts:61-84
    • 敏感数据脱敏中间件:server/src/middleware/security.ts:105-133

      flowchart TD
      Start(["进入安全中间件"]) --> CleanBody["清洗请求体 XSS"]
      CleanBody --> CleanQuery["清洗查询参数 XSS"]
      CleanQuery --> SetHeaders["设置安全响应头"]
      SetHeaders --> Next["调用 next()"]
      Next --> After["下游执行完成"]
      After --> MaskResp["脱敏响应中的敏感数据"]
      MaskResp --> End(["结束"])
      

图表来源

  • server/src/middleware/security.ts:6-133

章节来源

  • server/src/middleware/security.ts:1-154

限流中间件(流量控制)

  • 设计要点
    • 支持 Redis 与内存两种存储,Redis 不可用时自动回退。
    • 提供通用限流工厂与多场景限流器:API 全局、登录、短信、TTS、上传。
    • 超限时设置 Retry-After 并返回 429。
  • 执行顺序
    • 在认证/配额之后、业务逻辑之前安装,避免绕过配额直接刷接口。
  • 实际使用示例

    • 全局限流器:server/src/middleware/rate-limiter.ts:77-81
    • 登录限流器:server/src/middleware/rate-limiter.ts:86-91
    • 短信限流器:server/src/middleware/rate-limiter.ts:96-101
    • TTS 限流器:server/src/middleware/rate-limiter.ts:106-110
    • 上传限流器:server/src/middleware/rate-limiter.ts:115-119

      flowchart TD
      Start(["进入限流中间件"]) --> GenKey["生成限流键IP/用户/自定义"]
      GenKey --> Consume["尝试消耗配额"]
      Consume --> |成功| Next["调用 next()"]
      Consume --> |失败| Reject["设置 429 与 Retry-After"]
      Next --> End(["结束"])
      Reject --> End
      

图表来源

  • server/src/middleware/rate-limiter.ts:49-72

章节来源

  • server/src/middleware/rate-limiter.ts:1-120

性能中间件(监控指标)

  • 设计要点
    • 统计总请求数、平均响应时间、慢请求(阈值 1 秒)、端点级指标与错误率。
    • 提供获取指标与重置指标的辅助函数。
    • 在响应头中附加 X-Response-Time。
  • 执行顺序
    • 在安全中间件之后、路由之前安装,覆盖全链路。
  • 实际使用示例

    • 指标路由:server/src/app.ts:96-98
    • 指标导出函数:server/src/middleware/performance.ts:81-83

      flowchart TD
      Start(["进入性能监控"]) --> MarkStart["记录开始时间"]
      MarkStart --> CallNext["调用下游"]
      CallNext --> |正常| Calc["计算耗时并更新指标"]
      CallNext --> |异常| IncErr["增加错误计数并抛出"]
      Calc --> Slow{"是否慢请求?"}
      Slow --> |是| Warn["记录慢请求警告"]
      Slow --> |否| SetHdr["设置 X-Response-Time"]
      IncErr --> End(["结束"])
      Warn --> SetHdr --> End
      

图表来源

  • server/src/middleware/performance.ts:29-76

章节来源

  • server/src/middleware/performance.ts:1-110
  • server/src/app.ts:96-98

缓存中间件(读写缓存)

  • 设计要点
    • Redis 不可用时自动跳过缓存,不影响业务。
    • 支持自定义键生成器与键前缀,命中返回缓存、未命中写入缓存。
    • 提供批量清空缓存的中间件。
  • 执行顺序
    • 在业务逻辑之前安装,优先读取缓存。
  • 实际使用示例

    • 通用缓存工厂:server/src/middleware/cache.ts:13-48
    • 用户信息缓存:server/src/middleware/cache.ts:68-72
    • 书籍详情缓存:server/src/middleware/cache.ts:81-85

      flowchart TD
      Start(["进入缓存中间件"]) --> RedisAvail{"Redis 可用?"}
      RedisAvail --> |否| Next["跳过缓存,直接调用 next()"]
      RedisAvail --> |是| GenKey["生成缓存键"]
      GenKey --> GetCache["尝试获取缓存"]
      GetCache --> |命中| ReturnCache["设置 X-Cache=HIT 并返回缓存"]
      GetCache --> |未命中| Exec["执行业务逻辑"]
      Exec --> Ok{"状态码为 200 且有响应体?"}
      Ok --> |是| SetCache["写入缓存带 TTL"]
      Ok --> |否| Skip["不写入缓存"]
      SetCache --> SetHdr["设置 X-Cache=MISS"]
      Skip --> SetHdr
      ReturnCache --> End(["结束"])
      SetHdr --> End
      Next --> End
      

图表来源

  • server/src/middleware/cache.ts:13-48

章节来源

  • server/src/middleware/cache.ts:1-98

使用次数/字数限额中间件(配额校验)

  • 设计要点
    • 未登录时注入无限制配额;已登录则查询用户并重置当日使用次数。
    • 将用户配额与用户信息注入 ctx.state,供后续中间件与控制器使用。
    • 提供按字数的二次校验高阶中间件。
  • 执行顺序
    • 在认证之后、业务逻辑之前安装,确保配额生效。
  • 实际使用示例

    • 配额中间件:server/src/middleware/usageLimit.ts:7-49
    • 字数校验高阶中间件:server/src/middleware/usageLimit.ts:52-66
    • 会员配额定义:server/src/types/index.ts:120-124

      flowchart TD
      Start(["进入使用次数/字数限额中间件"]) --> HasUserId{"是否存在用户ID?"}
      HasUserId --> |否| InjectUnlim["注入无限制配额并继续"]
      HasUserId --> |是| LoadUser["查询用户并重置当日使用次数"]
      LoadUser --> CheckDaily{"是否超过日使用次数?"}
      CheckDaily --> |是| ThrowQuota["抛出配额超限错误"]
      CheckDaily --> |否| InjectQuota["注入用户配额与用户信息"]
      InjectQuota --> Next["调用 next()"]
      InjectUnlim --> Next
      ThrowQuota --> End(["结束"])
      Next --> End
      

图表来源

  • server/src/middleware/usageLimit.ts:7-49

章节来源

  • server/src/middleware/usageLimit.ts:1-66
  • server/src/types/index.ts:120-124

依赖关系分析

  • 中间件耦合与内聚
    • 认证中间件与使用次数/字数限额中间件存在天然依赖:限额需要用户上下文。
    • 限流中间件依赖 Redis 服务;当 Redis 不可用时自动回退内存限流器。
    • 缓存中间件依赖 Redis 服务;不可用时自动跳过。
    • 错误处理中间件作为全局兜底,不依赖其他中间件。
  • 外部依赖与集成点

    • Redis 服务:用于限流器与缓存。
    • Sentry:在应用启动时初始化,配合错误处理中间件统一上报。
    • Prisma:用于用户与配额查询。
    • JWT:用于认证中间件的令牌验证。

      graph TB
      subgraph "中间件"
      A["auth.ts"] --> B["usageLimit.ts"]
      B --> C["rate-limiter.ts"]
      C --> D["cache.ts"]
      E["errorHandler.ts"] -.->|.-> F["security.ts"]
      F -.-> G["performance.ts"]
      end
      subgraph "外部服务"
      R["Redis 服务"] --> C
      R --> D
      P["Prisma"] --> B
      S["Sentry"] --> E
      end
      

图表来源

  • server/src/middleware/auth.ts:1-81
  • server/src/middleware/usageLimit.ts:1-66
  • server/src/middleware/rate-limiter.ts:1-120
  • server/src/middleware/cache.ts:1-98
  • server/src/middleware/errorHandler.ts:1-67
  • server/src/middleware/security.ts:1-154
  • server/src/middleware/performance.ts:1-110

章节来源

  • server/src/app.ts:13-25
  • server/src/middleware/rate-limiter.ts:1-3
  • server/src/middleware/cache.ts:1-2
  • server/src/middleware/usageLimit.ts:1-4

性能考量

  • 中间件顺序对性能的影响
    • 错误处理与性能监控置于链路外层,避免重复统计与重复包裹。
    • 安全中间件在路由之前,减少无效请求进入业务逻辑的成本。
    • 限流与配额在路由之后、业务之前,避免无效计算与 IO。
  • Redis 回退策略
    • 限流与缓存均具备 Redis 不可用时的回退逻辑,保障稳定性。
  • 指标与告警
    • 性能中间件提供慢请求阈值与端点级指标,便于定位瓶颈。
  • 最佳实践
    • 将热点接口与高并发接口优先接入缓存中间件。
    • 对登录、短信等易被攻击的接口单独配置限流器。
    • 在开发环境开启详细错误输出,生产环境关闭堆栈输出。

故障排查指南

  • 常见问题与定位
    • 认证失败:检查 Authorization 头格式与 Token 是否过期;确认开发模式开关。
    • 429 频繁:检查限流键是否正确(IP/用户 ID),适当提高配额或延长窗口。
    • 缓存未生效:确认 Redis 连接状态与键前缀是否一致。
    • 慢请求告警:结合性能指标路由定位慢端点,优化数据库查询或第三方调用。
  • 调试步骤
    • 查看 HTTP 日志与性能指标路由输出。
    • 在开发环境打开堆栈信息,快速定位异常源。
    • 使用 Sentry 错误监控查看异常聚合与告警。

章节来源

  • server/src/middleware/errorHandler.ts:19-22
  • server/src/middleware/performance.ts:60-63
  • server/src/app.ts:96-98

结论

该中间件系统以 Koa 的洋葱模型为基础,构建了“安全—认证—配额—限流—缓存—性能—错误处理”的完整链路。通过模块化设计与可插拔组合,既满足了开发期的灵活性,也兼顾了生产期的稳定性与可观测性。建议在新增功能时遵循“前置安全、后置性能与错误兜底”的原则,确保中间件组合的一致性与可维护性。

附录

中间件配置参数与使用示例路径

  • 认证中间件
    • 强制认证:server/src/middleware/auth.ts:7-49
    • 可选认证:server/src/middleware/auth.ts:52-80
  • 错误处理中间件
    • 统一异常捕获与响应:server/src/middleware/errorHandler.ts:3-24
    • 业务错误类型:server/src/middleware/errorHandler.ts:27-67
  • 安全中间件
    • XSS 防护:server/src/middleware/security.ts:6-27
    • SQL 注入防护:server/src/middleware/security.ts:61-84
    • 敏感数据脱敏:server/src/middleware/security.ts:105-133
  • 限流中间件
    • 通用工厂与场景限流器:server/src/middleware/rate-limiter.ts:49-120
  • 性能中间件
    • 指标统计与导出:server/src/middleware/performance.ts:29-110
  • 缓存中间件
    • 通用工厂与常用缓存配置:server/src/middleware/cache.ts:13-98
  • 使用次数/字数限额中间件
    • 配额校验与字数校验:server/src/middleware/usageLimit.ts:7-66
    • 会员配额定义:server/src/types/index.ts:120-124

自定义中间件开发指南

  • 设计原则
    • 明确职责单一,避免过度耦合。
    • 保持与 Koa 的 next 模式兼容,确保异常可被统一处理。
    • 对外暴露可配置参数,支持键生成器、TTL、阈值等。
  • 开发步骤
    • 在 server/src/middleware 下新建文件,导出中间件函数。
    • 在 server/src/app.ts 中按需注册,注意顺序。
    • 在控制器中按需组合使用,必要时提供高阶中间件。
  • 调试建议
    • 在关键节点打印 ctx.method、ctx.path、ctx.status、ctx.response.headers。
    • 使用性能中间件与指标路由观察影响范围。

中间件组合使用最佳实践

  • 顺序建议
    • errorHandler → Sentry → performanceMonitor → httpLogger → xssProtection → sqlInjectionProtection → cors → koaBody/static/upload → router
    • 在路由层按需叠加:auth → usageLimit → rateLimiter → cache → controller
  • 场景化组合
    • 登录接口:auth + loginRateLimiter
    • 文档/公开接口:optionalAuth + cache
    • 高频查询接口:cache + rateLimiter
    • 付费生成接口:auth + usageLimit + ttsRateLimiter + cache