部署在单个 Cloudflare Worker 上的个人 AI 网关:同时提供 OpenAI 兼容接口(Chat Completions 与 Responses API)和 Anthropic Messages 接口,把多家服务商收拢到一个地址、一把密钥,失败自动切换到下一家。
面向一个人自用:没有用户体系、计费和配额,零构建,管理页拆成 HTML/CSS/JS 后由入口注入成单页打进 Worker。错误信息一律原文返回、原文显示,不做隐藏。
- 服务商管理:名称、ID、协议类型(OpenAI 兼容 / OpenAI Responses / Anthropic)、Base URL、API Key(页面只显示脱敏预览)、模型列表(可从服务商
/models拉取勾选)、启用、顺序、超时 - OpenAI 兼容接口:
/v1/chat/completions(流式 SSE 原样透传)、/v1/responses(OpenAI Responses API,含原生透传与跨协议转换)、/v1/embeddings、/v1/models;图片与语音:/v1/images/generations、/v1/images/edits、/v1/audio/transcriptions、/v1/audio/speech(TTS;对齐控制台网关并补充合成,按模型找到服务商后原样转发) - Anthropic 接口:
/v1/messages(含流式)、/v1/messages/count_tokens,Claude Code 可直接接入 - 协议全自动互转:三种入口(Chat Completions / Responses / Messages)都能调用任意协议的服务商,请求体(
messages⇄input/instructions)、响应体、流式 SSE 事件(Chunk ⇄ Responses 事件 ⇄ Anthropic 事件)、工具调用全自动无缝互转 - 模型寻址:
服务商 ID/模型,例如openrouter/google/gemini-2.5-pro;也可只写模型名(在已启用服务商的模型列表里找,不区分大小写);提供FlareRouter/auto(兼任auto),按容灾链从头尝试 - 容灾切换与智能熔断:失败(网络错误、超时、任何非 2xx)就按容灾链换下一个;同服务商遇 401/402/403/429 或欠费/额度耗尽等账号级故障时自动 0ms 快速熔断跳过该商剩余模型;流式请求只在上游开始返回之前切换;请求头
x-gateway-fallback: off可单次关闭,设置里也可整体关闭 - 调用密钥:
Authorization: Bearer、x-api-key或api-key鉴权;管理页可生成多个、随时查看明文、一键复制、吊销、删除;D1 存储明文与哈希 - 调用日志:存 D1,
ctx.waitUntil异步写;可按状态、容灾、协议、服务商、密钥、模型、错误关键词筛选,可清空;失败的每次尝试都记录上游原始报错 - 管理页:同一个 Worker 的
/admin,管理员密码登录;概览(含 HTTP 常见错误 400~504 速查表)、上游、密钥、测试、日志、设置(含容灾与隐私脱敏);模块化源码位于src/admin/(app.js、chat.js、i18n.js、style.css、chat.css、index.html);支持简体/繁体/English 三语切换;日夜模式默认跟随系统(与 FlarePanel 一致),可手动切换,含玻璃风格;「测试」支持多轮流式试聊、思考过程折叠与 Markdown(会话仅存本机浏览器) - 隐私与数据脱敏:出站前自动将敏感信息(API Key、数据库连接密码、IPv4、自定义敏感词)替换为确定性暗号(如
{{MASK_TOKEN_...}}),并在上游模型响应(含非流式与流式 SSE)时无缝还原;暗号基于确定性哈希,不破坏 Prompt Cache 命中率;支持针对单个服务商配置脱敏策略(如官方直连放行,第三方代理强制脱敏);记录日志时自动保护敏感内容,防止凭据落库
需要 Node.js 22+ 和一个 Cloudflare 账号(免费版即可)。
git clone https://github.com/HenryYannis/FlareRouter.git
cd FlareRouter
npm install
npx wrangler login
# 1. 创建 KV(服务商配置):把输出的 id 填进 wrangler.toml 的 [[kv_namespaces]]
npx wrangler kv namespace create flarerouter-config
# 2. 创建 D1(调用密钥 + 日志):把输出的 database_id 填进 wrangler.toml 的 [[d1_databases]]
npx wrangler d1 create flarerouter
# 3. 建表
npm run db:migrate
# 4. 设置管理员密码(交互输入,不会写进文件)
npx wrangler secret put ADMIN_PASSWORD
# 5. 部署
npx wrangler deploy默认部署到 https://flarerouter.<你的子域>.workers.dev。想用自己的域名:在 wrangler.toml 里把 workers_dev 改成 false,取消 routes 的注释并填上域名(域名要在同一个 Cloudflare 账号下),wrangler deploy 会自动创建 DNS 记录和证书;该子域名已有 DNS 记录的话先删掉。
部署后打开 https://你的地址/admin,用管理员密码登录:
- 「上游」里添加服务商(Base URL 一般以
/v1结尾)。模型列表可留空保存,再点「从服务商拉取」勾选写入;勾选随点随写入 - 「密钥」里生成密钥,明文只显示一次
- 「测试」里可多轮试聊(流式,走真实转发/容灾/日志);「日志」里看结果
- 「设置」里配置容灾链(留空则按服务商顺序取每家第一个模型)、日志保留与备份
以后更新代码只需要 npx wrangler deploy;有新的数据库迁移时再跑一次 npm run db:migrate(已执行过的迁移会自动跳过)。
想推送即部署:Cloudflare 面板 → Workers & Pages → 你的 Worker → 设置 → 构建,连接 GitHub 仓库的 main,部署命令填 npx wrangler d1 migrations apply DB --remote && npx wrangler deploy。
想把自己的 KV/D1 ID、域名提交到 Git 又不想公开时,可以建一个私有仓库作为下游:
- 私有仓库里只改
wrangler.toml等个人配置,其余文件不动,用git merge合并本仓库的main(不要 squash) - 在私有仓库加一个定时工作流:
git fetch本仓库 →git merge upstream/main→ 无冲突就推送,有冲突就开 issue - 想上游一更新就立即同步:在你的 fork 设置 Secrets
DOWNSTREAM_REPO(如you/flarerouter-private)和DOWNSTREAM_TOKEN(对下游有 Contents 读写权限的细粒度 PAT),.github/workflows/notify-downstream.yml会发repository_dispatch(类型flarerouter-updated);没配这两个 Secrets 时自动跳过
| 项 | 作用 |
|---|---|
[[kv_namespaces]] binding = "CONFIG" |
服务商配置、设置、登录失败计数;id 换成自己创建的 KV ID |
[[d1_databases]] binding = "DB" |
调用密钥、调用日志;database_id 换成自己创建的 D1 ID,表结构在 migrations/ |
workers_dev / routes |
用 workers.dev 子域还是自己的域名 |
[triggers] crons = ["0 19 * * *"] |
每天 UTC 19:00 按「日志保留天数」清理旧日志 |
[observability] |
Workers 日志与可观测性,默认开启 |
唯一的机密是 ADMIN_PASSWORD(管理页登录密码):
- 线上:
npx wrangler secret put ADMIN_PASSWORD,不要写进wrangler.toml - 本地:
cp .dev.vars.example .dev.vars,把ADMIN_PASSWORD=change-me改成自己的密码(.dev.vars已在.gitignore)
没设置 ADMIN_PASSWORD 时管理页无法登录。改密码会让所有旧会话失效。
服务商、容灾链和下面这些设置都存在 KV 里,在管理页修改:
- 容灾开关(默认开)
- 隐私与脱敏:全局脱敏开关、内置敏感规则(API Key、数据库连接串、IPv4)与自定义敏感词列表
- 每个服务商的脱敏策略(跟随全局 / 开启 / 关闭)、超时(默认 60 秒,最长 300 秒)和流式时是否补
stream_options.include_usage(默认开) - 日志保留天数(默认 30,0 为永久)
- 是否记录消息原文(默认关,只记元数据)
「设置 → 备份」可以导出/导入配置(导出文件含上游 Key 明文,注意保管;导入会整体覆盖当前服务商与设置)。
# 列出模型
curl https://ai.example.com/v1/models \
-H "Authorization: Bearer sk-fr-你的密钥"
# 非流式
curl https://ai.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-fr-你的密钥" \
-H "Content-Type: application/json" \
-d '{"model":"openrouter/google/gemini-2.5-pro","messages":[{"role":"user","content":"你好"}]}'
# 流式
curl -N https://ai.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-fr-你的密钥" \
-H "Content-Type: application/json" \
-d '{"model":"auto","stream":true,"messages":[{"role":"user","content":"写一句诗"}]}'
# 本次不容灾(失败直接返回上游原始错误)
curl https://ai.example.com/v1/chat/completions \
-H "Authorization: Bearer sk-fr-你的密钥" \
-H "x-gateway-fallback: off" \
-H "Content-Type: application/json" \
-d '{"model":"gemini/gemini-2.5-flash","messages":[{"role":"user","content":"hi"}]}'在 Cherry Studio、Chatbox、Cursor 等客户端里:API 地址填 https://ai.example.com/v1,密钥填 sk-fr-...,模型填 服务商 ID/模型 或 auto。
响应头会带上 x-gateway-provider、x-gateway-model、x-gateway-attempts、x-gateway-fallback、x-gateway-protocol,方便看这次实际走了哪家。
全部候选都失败时,HTTP 状态取最后一次上游的状态码(没有则 502),error.message 和 error.attempts 里有每一次尝试的原始报错。
GET /health 不需要密钥,返回 {"status":"ok","name":"flarerouter"},可用于存活检查。
管理页「服务商 → 添加服务商」,协议类型选「Anthropic Messages」:
- Base URL:
https://api.anthropic.com(带不带/v1都行) - API Key:
sk-ant-...(网关用x-api-key发给上游;anthropic-version默认2023-06-01,调用方带了就沿用调用方的) - 「从服务商拉取」会请求上游
/v1/models
其它提供 Anthropic 兼容接口的服务商也可以按这个类型添加。
| 入口 | 上游是 Anthropic | 上游是 OpenAI 兼容 (Chat) | 上游是 OpenAI Responses |
|---|---|---|---|
POST /v1/messages |
原样透传(只换 model,anthropic-version、anthropic-beta 沿用调用方的) |
转成 chat/completions,响应和流式转回 Anthropic 事件 | 自动转换请求体与流式事件 |
POST /v1/chat/completions |
转成 Messages,响应和流式转回 OpenAI chunk | 原样透传 | 自动转换请求体与流式事件 |
POST /v1/responses |
转成 Messages,响应和流式转回 Responses 事件 | 转成 chat/completions,响应和流式转回 Responses 事件 | 原样透传 |
转换覆盖:system、多轮、图片(base64 / URL)、tools / tool_use / tool_result、tool_choice、stop_reason ⇄ finish_reason、usage(含缓存命中)。
容灾链对三种入口都生效,可以跨协议切换(例如 Claude 官方 529 过载 → 换到 OpenRouter 上的模型),流式开始返回后不再切换。
响应头 x-gateway-protocol 显示这次是 入口->上游,例如 anthropic->openai;日志里也记录入口协议和上游协议。
/v1/messages/count_tokens:上游是 Anthropic 时直接转发;上游是 OpenAI 兼容时返回本地估算(响应头 x-gateway-estimated: 1)。
错误按入口协议的格式返回(/v1/messages 返回 {"type":"error","error":{...}}),message 里保留上游原始报错。
curl https://ai.example.com/v1/messages \
-H "x-api-key: sk-fr-你的密钥" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"auto","max_tokens":256,"messages":[{"role":"user","content":"你好"}]}'export ANTHROPIC_BASE_URL=https://ai.example.com
export ANTHROPIC_AUTH_TOKEN=sk-fr-你的调用密钥
# 指定模型(Claude Code 默认会发 claude-sonnet-… 这类官方名,网关里找不到就会 404)
export ANTHROPIC_MODEL=anthropic/claude-sonnet-4-5 # 服务商 ID/模型,或 auto
export ANTHROPIC_DEFAULT_HAIKU_MODEL=anthropic/claude-haiku-4-5 # 后台小任务用的快速模型
claude也可以写进 ~/.claude/settings.json:
{
"env": {
"ANTHROPIC_BASE_URL": "https://ai.example.com",
"ANTHROPIC_AUTH_TOKEN": "sk-fr-你的调用密钥",
"ANTHROPIC_MODEL": "anthropic/claude-sonnet-4-5",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "anthropic/claude-haiku-4-5"
}
}- 上面的
anthropic是你在管理页给服务商起的 ID,换成自己的;模型也可以指向 OpenAI 兼容的服务商(如openrouter/google/gemini-2.5-pro),网关会自动转协议。 - 用
ANTHROPIC_API_KEY代替ANTHROPIC_AUTH_TOKEN也行(发的是x-api-key头),网关两种都认。 - 也可以不设
ANTHROPIC_MODEL,而是把 Claude Code 发出的官方模型名(如claude-sonnet-4-5)直接写进某个服务商的模型列表,网关按模型名匹配。
对齐企业级安全网关(如 Magpie)的数据防护标准。在向大模型发送 Prompt、上下文代码或日志排错时,严防生产凭据(API Key、Bearer Token、数据库连接串、IPv4)与自定义私有词(如真实姓名、商业机密)泄露给外部大模型厂商。
- 双向无感还原(已恢复):
- 入站替换:网关在将请求发送给上游大模型前,毫秒级拦截敏感信息并替换为确定性暗号(如
{{MASK_TOKEN_...}}、{{MASK_CUSTOM_...}}); - 模型处理:上游大模型仅感知暗号占位符并完成推理或工具生成(Tool Calling);
- 出口还原:网关在把响应回传给调用方客户端的一瞬间,自动将暗号无缝还原为真实敏感词。客户端或自动化智能体拿到的是真值,无需改动任何下游业务逻辑。
- 入站替换:网关在将请求发送给上游大模型前,毫秒级拦截敏感信息并替换为确定性暗号(如
- 独创 SSE Token 碎片滑动拼接还原器:
攻克了大模型在流式打字输出时,将暗号切碎成多个极小微包(例如
{{、MASK_、CUSTOM_、218a703b、}})导致单帧正则无法匹配的行业难题。网关在滑动窗口拼齐闭合符的瞬间完成明文解密,流式打字与非流式同样顺畅。 - Prompt Cache 友好: 暗号采用确定性哈希算法,相同敏感词在请求中生成的暗号完全一致,完全不破坏 Anthropic / DeepSeek 的前缀缓存(Prompt Cache)命中率。
- 纯边缘 KV 持久化: 暗号映射由 Cloudflare KV 永久保存,克服了传统网关“只存单机内存、重启即失效”的痛点,支持跨会话、跨会话历史的多轮对话精准还原,且无需执行数据库迁移。
- 细粒度服务商策略:
每个服务商可单独配置脱敏规则(
继承全局/强制开启/强制放行)。例如对本地部署模型直连放行,对第三方中转代理强制开启脱敏。 - 日志安全审计: 写入 D1 的调用日志已自动过滤敏感内容,管理后台提供异步明细弹窗,支持安全核对脱敏前后的原词与占位符对照。
cp .dev.vars.example .dev.vars # 改成本地用的管理员密码
npm run db:migrate:local
npx wrangler dev # http://localhost:8787/admin
npm test # Miniflare 自测(假 OpenAI + 假 Anthropic 上游):鉴权、转发、协议互转、流式、容灾、日志、Cron 清理等
npm run check # wrangler deploy --dry-runGitHub Actions(.github/workflows/check.yml)在每次 PR 和推送到 main 时运行:语法检查、npm test、npm run check、gitleaks 密钥扫描。
- 请求体除了
model换成上游真实模型名,其余字段原样转发;流式请求默认补stream_options.include_usage(某个服务商不认可在编辑里关掉)。 - 上游没返回 usage 时,token 数按字数粗略估算。
- 超时只计到上游返回响应头为止,之后的流式输出不限时长。
- 服务商配置在每个 Worker 实例里缓存 30 秒;调用密钥鉴权缓存 30 秒(吊销在别的实例最多 30 秒后生效)。
- 管理员登录:连续 10 次密码错误按 IP 锁定 15 分钟;会话 7 天,Cookie 为 HttpOnly + Secure + SameSite=Strict。
- 日志默认保留 30 天,每天 UTC 19:00 由 Cron 清理;默认不记录消息原文。
- 图片生成 / 编辑、语音识别 / TTS 与 chat、embeddings、messages 一样走调用密钥鉴权,按模型解析服务商后原样转发(支持容灾);Anthropic 协议的服务商不接 embeddings 与媒体接口(容灾时自动跳过)。请求体默认上限 25MB,媒体超时默认 120 秒(可用环境变量
MAX_MEDIA_BYTES、MEDIA_TIMEOUT_MS调整)。不支持 Cloudflare Workers AI 绑定。 - 协议互转的限制:
- Anthropic → OpenAI:
cache_control、top_k、服务端工具(web_search 等)、引用(citations)会被丢弃;thinking转成reasoning_content,签名放在reasoning_signature。OpenAI 上游的reasoning_content会转成 thinking 块;没有签名的 thinking 在发回 Anthropic 前改成普通文本,避免无签名块被拒绝。PDF 文档转成 OpenAIfile片段,上游不支持时会报错。 - OpenAI → Anthropic:没传
max_tokens(或max_completion_tokens)时,先用「从服务商拉取」时记下的该模型输出上限(Anthropic 官方、OpenRouter 等会给),没有再默认 4096(显式 0 会保留);temperature截到 0–1;n、logprobs、seed不转发;json_object/json_schema会折进 system;带reasoning_signature的思考按 thinking 块送回。 - 跨协议时
stop_sequence命中会报成普通结束(OpenAI 不区分)。 - 工具的 JSON Schema 原样转发;个别 OpenAI 兼容服务商对 Schema 较挑剔(如不认
$schema、format),用 Claude Code 调这类上游时可能报 400,报错原文会直接显示。
- Anthropic → OpenAI:
/v1/messages/count_tokens不写调用日志;OpenAI 上游时是粗略估算。
- FlarePanel:Cloudflare Pages 多站点管理后台,管理评论、浏览量、会员账号和 R2 文件,同样零构建、纯 Cloudflare 部署。
MIT © 2026 程小宝



