从 AxonHub 到 thinrelay
起因
用 codex CLI、OpenRouter 这些工具时,每个都要直连不同的上游 API,密钥散落在各台 VPS 上。之前用 AxonHub 做统一网关,但它太重了——用户管理、模型映射、请求追踪,一堆我用不到的东西。我只需要一个东西:把请求转发到正确的上游,别丢流式数据。
于是决定自己写一个。叫 thinrelay,取 “thin proxy” 之意。
定位
先想清楚不做什么,比想做什么更重要:
- 不做用户管理 — 个人网关,不是 SaaS
- 不做 model mapping — 请求里写什么 model 就转发什么
- 不做请求日志/追踪 — 不存任何数据,不写数据库
- 不做 Web UI — 配置文件改完 reload 就行
要做的事就一件:统一入口,转发 API 请求,保留 SSE streaming。
技术选型
Go。原因很简单:
- 编译成单二进制,扔到 VPS 上就能跑,没有 runtime 依赖
net/http/httputil自带反向代理,原生支持 SSE flush- 我熟悉
依赖尽量少:yaml.v3(配置)、x/time/rate(限速)、utls(TLS 指纹伪装,后面说)。
开发过程
1. 骨架:config + HTTP server
先搭框架。YAML 配置文件定义网关的 listen address、API key、各上游的配置。HTTP server 用标准库 net/http,加一层 API key 校验中间件,加一个 /healthz 健康检查。
这部分没什么特别的,标准的 Go web server 模式。
2. Codex passthrough
Codex CLI 把 OAuth token 存在 ~/.codex/auth.json 里,明文 JSON。转发逻辑很简单:读 token → 构造请求 → 转发到 api.openai.com → 逐 chunk flush 回客户端。
func codexHandler(w http.ResponseWriter, r *http.Request) {
// 读 ~/.codex/auth.json 拿 token
// 构造转发请求,把 Authorization header 设上
// httputil.ReverseProxy 转发,FlushInterval 设成 -1 立即 flush
}
关键细节:ReverseProxy.FlushInterval = -1 让 SSE 数据逐 chunk 立即 flush,不缓冲。如果忘了这个,流式响应会卡住,客户端等半天一次性收到所有数据。
3. OpenRouter passthrough
更简单。OpenRouter 用 API key 认证,配置文件里填上就行。转发逻辑和 Codex 一样,只是 token 来源不同。
5. 限速中间件
用 golang.org/x/time/rate 做令牌桶限速。默认 20 RPM,模拟正常单用户的请求频率。防止请求太快被 Google 检测到异常。
6. 统一路由
最后把三个 provider 的 handler 接到一起:
/v1/chat/completions → model
/codex/v1/* → Codex 直通
/openrouter/v1/* → OpenRouter 直通
/healthz → 健康检查
统一入口 /v1/chat/completions 按 model 字段自动分流:model 名以 gemini 开头的走 AGY,其他的走 Codex。这样 CLI 工具只需要配一个 base URL,不用关心后端是哪个 provider。
编译
go build -o thinrelay .,12MB 单二进制。没有 Docker,没有数据库,没有外部依赖。
最终代码结构
thinrelay/
├── main.go # 入口,HTTP server + 路由
├── config.go # YAML 配置加载
├── codex.go # Codex passthrough
├── openrouter.go # OpenRouter passthrough
├── format.go # OpenAI ↔ Gemini 格式转换
├── middleware.go # API key 校验 + 限速
├── stream.go # SSE streaming 支持
├── go.mod
└── config.example.yaml
约 1100 行 Go 代码。
部署
- 网关 VPS 上装 agy 并登录 → token 存进 keyring
- 网关 VPS 上装 codex 并登录 → token 存进
~/.codex/auth.json cp config.example.yaml config.yaml,改 api_key 和 openrouter key./thinrelay -config config.yaml- 业务 VPS 上配
OPENAI_BASE_URL指向网关
总结
一天写完,1100 行代码,12MB 二进制。做的事情很简单:统一入口、转发请求、保留流式。不做的事情很明确:不存数据、不做多用户、不做 Web UI。
thinrelay 不会成为开源项目,但作为个人工具,它刚好够用。AxonHub 能做的事它做不了,但 AxonHub 做的 90% 我都不需要。剩下的 10%,thinrelay 做到了。
- 点赞
- 收藏
- 关注作者
评论(0)