JianFeeeee
7836b95a84
fix(gateway): ?key= 传完整 key 会让 /api/stats panic
给 usage 插件探路时撞出来的,与插件无关。
Snapshot 的统计 map 以**掩码** key id 为键(keyID(req.Key))——by_key 返回什么、
面板就传什么。而 exportKey 对 admin 允许 ?key= 任意值,于是:
byKey = map[string]*Stat{key: s.byKey[key]} // 传完整 key → 零值 nil *Stat
...
rows() 里 Stat: *v // 解引用 nil → panic
实测(改动前,线上):
/api/stats?period=day&limit=1&key=sk-gw-7ffe12c5cbacec40bd39a7291df9a9ed
→ curl: (52) Empty reply from server
→ 日志: http: panic serving …: invalid memory address or nil pointer dereference
llmsproxy/internal/gateway.rows stats.go:771
net/http 会 recover 单个连接所以进程不死,但客户端拿到空响应,日志里每次一条
panic 栈。任何「这个 key 用了多少」的问法(key 已配但当天无流量、period 把它
的历史滤掉了)都会命中 —— 而零正是那个问题的答案,不是错误。
三处防御,因为同一个错误形状有四个入口:
- rows() 跳过 nil 而不是解引用(调用方不止 Snapshot)
- byStatus 的两处遍历同理
- PeriodSnapshot 的 buckets[k] 同理
by_key 仍保留该 key 的一行零值:面板按行存在与否渲染,缺行会让 key 整个消失。
判据:internal/gateway/stats_unknown_key_test.go(5 个测试)。反向验证过——
把 Snapshot 与 rows 的修复撤掉,TestSnapshotUnknownKeyDoesNotPanic 立刻 panic。
(cherry picked from commit af977efbf7)
2026-10-07 17:37:22 +08:00
..
2026-10-07 17:37:22 +08:00
2026-10-04 14:50:46 +08:00
2026-09-27 17:12:03 +08:00
2026-10-06 15:02:42 +08:00
2026-10-02 12:55:54 +08:00
2026-10-02 12:55:54 +08:00
2026-08-28 12:02:46 +08:00
2026-10-06 15:02:42 +08:00
2026-10-06 15:02:42 +08:00
2026-09-27 17:12:03 +08:00
2026-10-02 15:44:50 +08:00
2026-10-06 15:02:42 +08:00
2026-10-06 15:02:42 +08:00
2026-10-06 15:02:42 +08:00
2026-10-07 17:37:22 +08:00
2026-10-06 15:02:42 +08:00
2026-10-06 15:02:42 +08:00
2026-10-06 15:02:42 +08:00
2026-09-28 23:42:48 +08:00
2026-10-02 08:47:08 +08:00
2026-10-03 07:45:54 +08:00
2026-09-28 23:42:48 +08:00
2026-09-27 18:44:41 +08:00
2026-09-27 18:44:41 +08:00
2026-09-27 18:44:41 +08:00
2026-09-28 23:42:48 +08:00
2026-10-03 07:45:54 +08:00
2026-08-30 08:04:22 +08:00
2026-09-27 17:12:03 +08:00
2026-10-04 14:50:46 +08:00
2026-10-04 14:50:46 +08:00
2026-10-02 01:03:39 +08:00
2026-10-04 14:50:46 +08:00
2026-10-05 08:17:57 +08:00
2026-10-06 15:02:42 +08:00
2026-10-01 20:36:48 +08:00
2026-10-01 18:15:29 +08:00
2026-10-01 23:37:17 +08:00
2026-10-03 10:32:51 +08:00
2026-10-04 14:50:46 +08:00
2026-10-07 17:37:22 +08:00
2026-08-30 09:29:42 +08:00
2026-10-07 17:37:22 +08:00
2026-10-07 17:37:22 +08:00
2026-09-28 22:19:12 +08:00
2026-10-01 20:36:48 +08:00
2026-10-06 15:02:42 +08:00
2026-10-07 17:37:22 +08:00
2026-10-04 07:05:36 +08:00
2026-10-04 14:50:46 +08:00
2026-09-27 19:02:13 +08:00