中间件扩展.md 22 KB

中间件扩展

本文引用的文件

  • server/src/app.ts
  • server/src/middleware/auth.ts
  • server/src/middleware/errorHandler.ts
  • server/src/middleware/cache.ts
  • server/src/middleware/security.ts
  • server/src/middleware/rate-limiter.ts
  • server/src/middleware/performance.ts
  • server/src/middleware/usageLimit.ts
  • server/src/services/redis.service.ts
  • server/src/modules/auth/auth.controller.ts
  • server/src/modules/tts/tts.controller.ts
  • server/src/types/index.ts
  • server/src/config/index.ts

目录

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

简介

本文件面向AI有声书生成平台的中间件扩展与实践,围绕认证、错误处理、缓存、安全与限流等关键中间件,系统阐述其执行顺序、上下文传递、异常处理机制,并提供自定义中间件开发模板、配置管理、性能优化、链路设计、调试与监控、测试策略与部署注意事项。目标是帮助开发者在保持现有中间件体系稳定的同时,安全地扩展新的中间件能力。

项目结构

中间件位于 server/src/middleware 目录,应用入口 server/src/app.ts 统一注册中间件;各业务模块通过路由控制器使用中间件。Redis 服务封装于 server/src/services/redis.service.ts,供缓存与限流等中间件使用。

graph TB
A["应用入口<br/>server/src/app.ts"] --> B["错误处理中间件<br/>server/src/middleware/errorHandler.ts"]
A --> C["性能监控中间件<br/>server/src/middleware/performance.ts"]
A --> D["日志中间件<br/>server/src/services/logger.service.ts"]
A --> E["安全中间件XSS/SQL注入<br/>server/src/middleware/security.ts"]
A --> F["CORS 中间件<br/>@koa/cors"]
A --> G["请求体解析<br/>koa-body/bodyparser"]
A --> H["静态文件挂载<br/>koa-mount/serve"]
subgraph "业务路由"
R1["认证路由<br/>server/src/modules/auth/auth.controller.ts"]
R2["TTS 路由<br/>server/src/modules/tts/tts.controller.ts"]
end
A --> R1
A --> R2
subgraph "服务层"
S1["Redis 服务<br/>server/src/services/redis.service.ts"]
end
B -. 使用 .-> S1
C -. 使用 .-> S1
E -. 使用 .-> S1

图表来源

  • server/src/app.ts:63-130
  • server/src/middleware/errorHandler.ts:1-67
  • server/src/middleware/performance.ts:1-110
  • server/src/middleware/security.ts:1-154
  • server/src/services/redis.service.ts:1-274
  • server/src/modules/auth/auth.controller.ts:1-94
  • server/src/modules/tts/tts.controller.ts:1-274

章节来源

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

核心组件

  • 认证中间件:提供强制认证与可选认证两种模式,基于 JWT 校验,将用户信息写入 ctx.state.user。
  • 错误处理中间件:统一捕获异常,输出结构化错误响应,并在开发环境输出堆栈。
  • 缓存中间件:基于 Redis 的响应缓存与键空间清理,支持自定义键生成器与 TTL。
  • 安全中间件:XSS 过滤、SQL 注入检测、敏感数据脱敏与安全响应头设置。
  • 限流中间件:基于 rate-limiter-flexible 的内存/Redis 限流器,支持多场景限流策略。
  • 性能监控中间件:统计总请求数、平均响应时间、慢请求、错误率与端点级指标。
  • 使用配额中间件:按会员等级校验每日使用次数与字数配额,写入 ctx.state.userQuota 与 ctx.state.userInfo。

章节来源

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

架构总览

中间件在应用启动时按顺序注册,形成“洋葱模型”调用链。每个中间件在 next() 前后可进行前置处理与后置处理,异常在错误处理中间件集中捕获。

sequenceDiagram
participant Client as "客户端"
participant App as "Koa 应用<br/>server/src/app.ts"
participant EH as "错误处理中间件"
participant PM as "性能监控中间件"
participant SEC as "安全中间件"
participant RL as "限流中间件"
participant AUTH as "认证中间件"
participant USAGE as "使用配额中间件"
participant CTRL as "业务控制器"
Client->>App : HTTP 请求
App->>EH : 进入错误处理
EH->>PM : 调用 next()
PM->>SEC : 调用 next()
SEC->>RL : 调用 next()
RL->>AUTH : 调用 next()
AUTH->>USAGE : 调用 next()
USAGE->>CTRL : 调用 next()
CTRL-->>USAGE : 返回响应或抛错
USAGE-->>AUTH : 返回响应或抛错
AUTH-->>RL : 返回响应或抛错
RL-->>SEC : 返回响应或抛错
SEC-->>PM : 返回响应或抛错
PM-->>EH : 返回响应或抛错
EH-->>Client : 结构化响应

图表来源

  • server/src/app.ts:63-130
  • server/src/middleware/errorHandler.ts:1-24
  • server/src/middleware/performance.ts:29-76
  • server/src/middleware/security.ts:6-27
  • server/src/middleware/rate-limiter.ts:49-72
  • server/src/middleware/auth.ts:7-49
  • server/src/middleware/usageLimit.ts:6-49

详细组件分析

认证中间件

  • 强制认证:读取 Authorization Bearer Token,校验签名与过期,失败抛出未授权错误;开发模式可通过环境变量跳过。
  • 可选认证:允许未登录访问,若携带无效 Token 则回退为测试用户,便于联调。
  • 上下文传递:将用户信息写入 ctx.state.user,后续中间件与控制器可读取。

    flowchart TD
    Start(["进入认证中间件"]) --> CheckDev{"开发模式且禁用认证?"}
    CheckDev --> |是| UseTestUser["写入测试用户到 ctx.state.user"] --> Next1["调用 next()"]
    CheckDev --> |否| GetHeader["读取 Authorization 头"]
    GetHeader --> HasHeader{"存在且格式正确?"}
    HasHeader --> |否| ThrowUnauthorized["抛出未授权错误"] --> End
    HasHeader --> |是| Verify["校验 JWT 签名与有效期"]
    Verify --> OK{"校验通过?"}
    OK --> |否| ThrowAuthFail["抛出认证失败/过期/无效"] --> End
    OK --> |是| SetUser["写入用户信息到 ctx.state.user"] --> Next2["调用 next()"] --> End
    

图表来源

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

章节来源

  • server/src/middleware/auth.ts:1-81
  • server/src/types/index.ts:66-82

错误处理中间件

  • 统一捕获异常,设置状态码与结构化响应体;开发环境附加堆栈信息。
  • 提供多种业务错误类(未授权、禁止、资源不存在、请求错误、配额超限)以表达不同语义。

    flowchart TD
    Enter(["进入错误处理中间件"]) --> TryNext["尝试执行下游中间件/控制器"]
    TryNext --> Catch{"是否抛出异常?"}
    Catch --> |否| ReturnResp["返回正常响应"]
    Catch --> |是| BuildResp["构造错误响应体<br/>状态码/错误码/消息"]
    BuildResp --> DevEnv{"开发环境?"}
    DevEnv --> |是| AddStack["附加堆栈信息"] --> Send
    DevEnv --> |否| Send["发送错误响应"]
    ReturnResp --> End
    Send --> End
    

图表来源

  • server/src/middleware/errorHandler.ts:1-24
  • server/src/middleware/errorHandler.ts:26-67

章节来源

  • server/src/middleware/errorHandler.ts:1-67

缓存中间件

  • 基于 Redis 的响应缓存:命中则直接返回缓存并设置 X-Cache 头;未命中执行下游逻辑并将成功响应缓存。
  • 键生成策略:支持自定义 keyGenerator 与 keyPrefix,默认使用 method:url。
  • 清理缓存:提供按前缀批量删除能力,便于灰度与维护。

    flowchart TD
    Enter(["进入缓存中间件"]) --> RedisOK{"Redis 可用?"}
    RedisOK --> |否| Next["跳过缓存,直接调用 next()"] --> End
    RedisOK --> |是| GenKey["生成缓存键支持自定义"]
    GenKey --> GetCache["从 Redis 读取缓存"]
    GetCache --> Hit{"命中?"}
    Hit --> |是| SetHeaderHit["设置 X-Cache: HIT"] --> ReturnCache["返回缓存内容"] --> End
    Hit --> |否| Exec["调用 next() 执行下游"]
    Exec --> StatusOK{"状态码为 200 且有 body?"}
    StatusOK --> |否| End
    StatusOK --> |是| SetHeaderMiss["设置 X-Cache: MISS"] --> SaveCache["写入 Redis带 TTL"] --> End
    

图表来源

  • server/src/middleware/cache.ts:13-48
  • server/src/middleware/cache.ts:54-61
  • server/src/services/redis.service.ts:43-82

章节来源

  • server/src/middleware/cache.ts:1-98
  • server/src/services/redis.service.ts:1-274

安全中间件

  • XSS 防护:递归过滤请求体与查询参数中的危险字符与脚本标签,设置安全响应头。
  • SQL 注入防护:对查询参数与请求体进行模式匹配检测,发现非法字符直接返回错误。
  • 敏感数据脱敏:对响应体中密码、令牌等字段进行脱敏处理。

    flowchart TD
    Enter(["进入安全中间件"]) --> XSS["递归过滤请求体/查询参数中的 XSS"]
    XSS --> SetHeaders["设置安全响应头"]
    SetHeaders --> Next["调用 next()"]
    Next --> PostFilter{"是否需要脱敏响应?"}
    PostFilter --> |是| Mask["递归脱敏敏感字段"] --> End
    PostFilter --> |否| End
    

图表来源

  • server/src/middleware/security.ts:6-27
  • server/src/middleware/security.ts:61-84
  • server/src/middleware/security.ts:105-133

章节来源

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

限流中间件

  • 支持内存与 Redis 两套限流器,Redis 不可用时自动降级。
  • 提供通用 createRateLimiter 与多个场景化限流器(API 全局、登录、短信、TTS、上传)。
  • 限流触发时设置 Retry-After 并返回 429。

    flowchart TD
    Enter(["进入限流中间件"]) --> GetLimiter["获取/创建限流器Redis/内存"]
    GetLimiter --> GenKey["生成限流键IP/用户/手机号等"]
    GenKey --> Consume["尝试消费 1 个配额"]
    Consume --> OK{"是否允许?"}
    OK --> |是| Next["调用 next()"] --> End
    OK --> |否| Reject["设置 Retry-After 与 429 响应"] --> End
    

图表来源

  • server/src/middleware/rate-limiter.ts:18-72
  • server/src/middleware/rate-limiter.ts:77-120

章节来源

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

性能监控中间件

  • 统计总请求数、平均响应时间、慢请求(阈值 1 秒)、错误率与端点级指标。
  • 在响应头中附加 X-Response-Time,便于前端与网关侧观测。
  • 提供指标查询路由与重置能力。

    flowchart TD
    Enter(["进入性能监控中间件"]) --> Start["记录开始时间"]
    Start --> Next["调用 next()"]
    Next --> Done{"执行成功?"}
    Done --> |是| Calc["计算耗时并更新全局与端点指标"] --> Slow{"是否慢请求?"}
    Slow --> |是| Warn["记录慢请求警告"] --> SetHeader["设置 X-Response-Time"] --> End
    Slow --> |否| SetHeader --> End
    Done --> |否| IncErr["增加错误计数"] --> Throw["向上抛出异常"] --> End
    

图表来源

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

章节来源

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

使用配额中间件

  • 对未登录用户写入无限制配额;对已登录用户按会员等级检查每日使用次数与字数配额。
  • 将用户配额与用户信息写入 ctx.state,供后续中间件与控制器使用。

    flowchart TD
    Enter(["进入使用配额中间件"]) --> CheckUser{"是否存在用户ID?"}
    CheckUser --> |否| SetUnlimited["写入无限制配额到 ctx.state.userQuota"] --> Next["调用 next()"] --> End
    CheckUser --> |是| LoadUser["查询用户并校验存在性"]
    LoadUser --> ResetDaily{"是否跨日?"}
    ResetDaily --> |是| UpdateDaily["重置每日使用次数"] --> CheckQuota["按会员等级获取配额"]
    ResetDaily --> |否| CheckQuota
    CheckQuota --> DailyOK{"是否超过每日次数?"}
    DailyOK --> |是| ThrowDaily["抛出配额超限错误"] --> End
    DailyOK --> |否| WriteState["写入 ctx.state.userQuota 与 ctx.state.userInfo"] --> Next --> End
    

图表来源

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

章节来源

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

依赖关系分析

  • 中间件之间通过 Koa 的 next() 串联,形成明确的前后置处理边界。
  • 错误处理中间件作为最外层,统一兜底异常。
  • 安全中间件在认证之前,确保输入与响应均经过净化与保护。
  • 限流与配额中间件在认证之后,利用 ctx.state.user 进行精细化控制。
  • 缓存中间件通常置于限流/认证之后,避免缓存污染。
  • Redis 服务被缓存与限流中间件共享,需保证连接可用性与稳定性。

    graph LR
    EH["错误处理"] --> PM["性能监控"]
    PM --> SEC["安全中间件"]
    SEC --> RL["限流中间件"]
    RL --> AUTH["认证中间件"]
    AUTH --> USAGE["使用配额中间件"]
    USAGE --> CTRL["业务控制器"]
    EH -.-> REDIS["Redis 服务"]
    PM -.-> REDIS
    RL -.-> REDIS
    CACHE["缓存中间件"] -.-> REDIS
    

图表来源

  • server/src/app.ts:63-130
  • server/src/middleware/cache.ts:13-48
  • server/src/middleware/rate-limiter.ts:18-43
  • server/src/services/redis.service.ts:43-82

章节来源

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

性能考量

  • 缓存命中优先:合理设置 TTL 与键生成策略,避免热点键竞争与雪崩。
  • 限流降级:Redis 不可用时自动切换内存限流器,保障服务可用性。
  • 响应头可观测:X-Response-Time 与 X-Cache 头便于前端与网关侧监控。
  • 慢请求告警:慢请求计数与端点级指标可用于定位瓶颈。
  • 配额控制:结合会员等级与字数限制,避免单用户过度占用资源。

故障排查指南

  • 认证失败:检查 Authorization 头格式与 Token 有效性;开发模式确认 AUTH_ENABLED 配置。
  • 缓存异常:确认 Redis 连接状态与键空间权限;观察 X-Cache 头判断命中/未命中。
  • 限流触发:查看 Retry-After 响应头与限流键(IP/用户/手机号),调整策略或白名单。
  • 安全拦截:关注 SQL 注入检测规则与 XSS 过滤结果,必要时放宽或定制规则。
  • 错误响应:生产环境查看结构化错误体,开发环境查看堆栈信息定位问题。

章节来源

  • server/src/middleware/auth.ts:7-49
  • server/src/middleware/cache.ts:42-46
  • server/src/middleware/rate-limiter.ts:60-71
  • server/src/middleware/security.ts:69-83
  • server/src/middleware/errorHandler.ts:9-23

结论

该中间件体系以“洋葱模型”清晰划分职责边界,通过统一的错误处理、安全防护、性能监控与缓存/限流机制,保障了平台在高并发与复杂业务场景下的稳定性与可运维性。扩展新中间件时,应遵循现有顺序与上下文约定,确保异常可兜底、性能可观测、配置可治理。

附录

中间件执行顺序与最佳实践

  • 推荐顺序:错误处理 → Sentry → 性能监控 → 日志 → 安全 → CORS → 请求体解析 → 静态文件 → 限流 → 认证 → 使用配额 → 业务控制器。
  • 上下文传递:仅在 ctx.state 中存放必要信息,避免污染请求体与响应体。
  • 异常处理:优先使用业务错误类,便于统一处理与前端提示。

章节来源

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

自定义中间件开发模板(步骤)

  • 定义函数签名:接收 ctx 与 next,返回 Promise。
  • 前置处理:读取请求上下文,进行参数校验或预处理。
  • 调用 next:等待下游执行。
  • 后置处理:根据 ctx 状态设置响应头或进行日志记录。
  • 异常捕获:在中间件内捕获并抛出业务错误类,交由错误处理中间件统一输出。
  • 章节来源

    • server/src/middleware/errorHandler.ts:26-67

    配置管理要点

    • 认证:开发模式可通过环境变量控制是否启用强制认证。
    • JWT:密钥需与签发端一致,避免跨环境不一致导致的认证失败。
    • Redis:连接参数与可用性直接影响缓存与限流功能。
    • 模型与供应商:统一在配置中心管理,便于动态切换与灰度发布。

    章节来源

    • server/src/middleware/auth.ts:8-18
    • server/src/config/index.ts:77-81
    • server/src/services/redis.service.ts:7-38

    性能优化技巧

    • 缓存:热点接口开启缓存,合理设置 TTL;对幂等读接口优先走缓存。
    • 限流:区分不同场景与用户身份,避免一刀切导致的误伤。
    • 监控:结合慢请求与端点指标,定位性能瓶颈;定期清理慢请求日志。
    • 配额:按会员等级差异化配额,提升付费转化与资源利用率。

    章节来源

    • server/src/middleware/cache.ts:13-48
    • server/src/middleware/rate-limiter.ts:49-72
    • server/src/middleware/performance.ts:29-76
    • server/src/middleware/usageLimit.ts:6-49

    调试方法与监控指标

    • 调试:开启开发环境日志与堆栈输出;使用 X-Response-Time 与 X-Cache 头辅助定位。
    • 指标:总请求数、平均响应时间、慢请求、错误率、端点级指标与错误率百分比。
    • 路由:/api/metrics 提供当前指标快照,可用于仪表盘展示。

    章节来源

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

    测试策略与部署注意事项

    • 单元测试:针对中间件的前置/后置逻辑与异常分支编写用例。
    • 集成测试:模拟真实请求链路,覆盖认证、缓存、限流与安全场景。
    • 部署:确保 Redis 服务可用;生产环境关闭开发模式认证豁免;按需开启全局限流中间件。
    • 回滚:限流与缓存变更需具备快速回滚策略,避免影响线上流量。

    章节来源

    • server/src/app.ts:133-192
    • server/src/services/redis.service.ts:246-255

    使用示例参考

    • 认证路由:在控制器中使用认证中间件保护用户信息接口。
    • 可选认证:TTS 生成接口使用可选认证,便于未登录用户预览体验。
    • 使用配额:在控制器中读取 ctx.state.userQuota 与 ctx.state.userInfo 进行业务校验。

    章节来源

    • server/src/modules/auth/auth.controller.ts:54-64
    • server/src/modules/tts/tts.controller.ts:52-127
    • server/src/middleware/usageLimit.ts:44-49