3.8 KiB
3.8 KiB
4.2 请求处理链路
:::tip 链路概览
一个典型 API 请求经过:浏览器 →(Nginx/Vite 代理)→ 中间件链 → 反射路由绑定 → handler → service → repository → 数据库 → 统一信封返回。本页以 GET /api/example/page 为例逐阶段拆解。
:::
第一阶段:网络层
前端经封装发起请求(ui/src/api/tool/example.ts):
// ui/src/api/tool/example.ts(摘录)
import { http } from '@/utils/http/axios';
// Authorization: Bearer <access_token> 由请求拦截器自动携带
export function getExamplePage(params?: Record<string, any>) {
return http.request({ url: '/example/page', method: 'GET', params });
}
开发期 Vite 代理转发(ui/.env.development):
VITE_PROXY=[["/api", "http://127.0.0.1:8000/api"]]
生产由 Nginx 反代到 8000(见 deploy/nginx.conf)。
第二阶段:中间件链(顺序勿动)
trace 分配 trace_id,后续全部日志可关联
↓
CORS 跨域响应头(cors.allowOrigin)
↓
Metrics Prometheus 指标采集(请求数/耗时)
↓
Response 统一信封出口 + panic 恢复(必须包住其后全部 handler)
↓
RateLimit 固定窗口限流(认证接口配额更严)
↓
Demo 演示模式:写操作拒绝,读与登录放行
↓
JWT 解析 Token,注入身份(公开接口跳过)
↓
Tenant 加载租户上下文(白名单表隔离依据)
↓
Authz 按路由元数据 Permission 校验权限点
↓
OperationLog 采集请求摘要,链尾异步落库(须读到最终响应)
顺序是设计约束:trace 最先(日志依赖 trace_id);Response 在业务前(panic 恢复包住全链);限流/演示在身份前(防未认证高频攻击);JWT → 租户 → 权限逐层依赖前置注入的身份;日志链尾采集。
第三阶段:路由绑定
router.Bind 已在启动期把 GET /api/example/page 注册到 Gin 路由树。请求命中后,包装函数执行:
绑定写入:query(pageNo/pageSize/name/type/status/keyword)→ body → path
│ 同名后写覆盖,最终 path > body > query
▼
binding 标签校验(失败直接 4xx 信封返回,不进 handler)
│
▼
构造 dto.ExamplePageReq → 调用 CExample.Page
第四阶段:四件套调用
// handler:一行委托
service.Example.Page(ctx, req)
// service:委托基座
list, total, err := exampleSpec.Page(ctx, req, req.GetPageNo(), req.GetPageSize())
// ModuleSpec:applyFilters 固定顺序生效
Model(Ctx 已注入 del_flag=0)→ LikeFields(name) → EqFields(type,status)
→ KeywordFields → Filter → DataScope → OrderBy → 分页 Find
ctx 贯穿全链——身份、租户、事务连接都挂在 ctx 上,repository 经 db.FromContext(ctx) 取连接。
第五阶段:响应与日志
service 返回 PageData[ExampleItem]
↓
绑定层包装函数调用 response.Ok(data)
↓
Response 中间件信封输出 {code:0, ok:true, msg, data}
↓
OperationLog 中间件读取最终响应摘要,异步写 gin_operation_log
(LogType=query 时还受 operationLog.logQuery 开关控制)
失败路径:binding 校验失败 / apperr 错误 / 普通 error / panic,全部经 Response 中间件映射为对应 code 的 JSON 信封,绝不出现 HTML 错误页(NoRoute 也返回 JSON)。
关键观察点
| 阶段 | 观察手段 |
|---|---|
| 全链追踪 | 响应头/日志中的 trace_id |
| SQL | database.default.debug=true 打印 SQL |
| 权限 | Swagger(/swagger)查看接口权限码 |
| 指标 | /metrics 看请求计数与耗时分布 |
| 日志落库 | gin_operation_log 表 |