# F. 中间件执行顺序 :::tip 说明 全局中间件链(顺序勿动):trace → CORS → metrics → response → ratelimit → demo → JWT → tenant → authz → operation_log。每个请求按此顺序穿过。 ::: ## 执行表 | # | 中间件 | 职责 | 拦截行为 | ctx 写入 | |---|---|---|---|---| | 1 | Trace | trace_id + 请求元信息 | 不拦截 | trace_id、IP、UA、方法、URL | | 2 | CORS | 跨域响应头 | OPTIONS 204 终止 | 无 | | 3 | Metrics | Prometheus 计数/耗时 | 不拦截 | 无 | | 4 | Response | 统一信封 + panic 恢复 | 错误时写信封终止 | 响应码/体记录 | | 5 | RateLimit | 固定窗口限流 | 超限拒绝 | 拒绝原因 | | 6 | Demo | 演示模式拒写 | 非 GET/HEAD/OPTIONS 且非公开路径拒绝 | 无 | | 7 | JWT | 令牌解析、身份注入 | 401 | 身份、jti/exp、角色权限 | | 8 | Tenant | 租户状态校验 | 禁用/过期拒绝 | 无(读身份) | | 9 | Authz | 功能权限校验 | 403 | 拒绝原因 | | 10 | OperationLog | 操作日志异步落库 | 不拦截 | 无(读响应记录) | 另有链外兜底:`gin.CustomRecovery`(静态资源等业务链之外的 panic)。 ## 顺序约束理由 - trace 最先:后续一切日志依赖 trace_id - Response 在业务前:panic 恢复包住全部 handler;错误出口统一 - ratelimit/demo 在身份前:防未认证高频攻击 - JWT → tenant → authz 逐层依赖前置注入的身份 - operation_log 链尾:须读到最终响应才采集 ## 免登录判定(IsPublicRequest) 两个来源汇合: | 来源 | 内容 | |---|---| | 基础设施白名单 | /api/health、/api.json、/swagger*、/metrics | | 路由元数据 | RouteSpec.Public=true(登录/验证码/令牌兑换) | ## 拒绝类请求的可观测差异 | 拒绝 | 操作日志 | metrics 归类 | |---|---|---| | 限流 / 权限 403 | 不记录 | denied | | 租户拒绝 | 不记录 | error | | 未认证 401 | 不记录 | —(JWT 层) | ## 相关 - [4.2 请求处理链路](/zh/architecture/request-flow.html) - [5.17 链路追踪与指标](/zh/core/trace-metrics.html)