Skip to content

feat(core): 支持 BOTMUX_PUBLIC_URL 让自建反代场景的 dashboard/终端链接走单域名前门#395

Open
xu4wang wants to merge 1 commit into
deepcoldy:masterfrom
xu4wang:feat/public-url-links
Open

feat(core): 支持 BOTMUX_PUBLIC_URL 让自建反代场景的 dashboard/终端链接走单域名前门#395
xu4wang wants to merge 1 commit into
deepcoldy:masterfrom
xu4wang:feat/public-url-links

Conversation

@xu4wang

@xu4wang xu4wang commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

背景 / 为什么

没接中心平台、但用 nginx 等反向代理把 dashboard 暴露到单一公网/内网域名的用户,此前:

  • dashboard 链接始终带 :7891(没有外部端口开关),走不到 nginx :80 vhost;
  • 卡片「打开web终端 / 获取操作链接」吐的是 per-bot 终端代理的 IP:端口(如 192.168.28.45:8801/s/<id>),外网打不开;且多 bot 各自不同端口,单口反代覆盖不到。

中心平台模式(远程访问 + 绑定)本就会把这些链接翻转成 https://m-<id>.<平台域名>/… 的干净无端口形态。本 PR 把同样的能力开放给「自建反代」场景,无需接平台。

改了什么

新增环境变量 BOTMUX_PUBLIC_URL(scheme://host[:port],尾斜杠会被去掉)。设置后:

  • dashboard 链接 → <BASE>/?t=<token>
  • 卡片终端链接 → <BASE>/s/<sessionId>(读)/ <BASE>/s/<sessionId>?token=<workerToken>(写)

二者都走 dashboard 前门(dashboard 已把 /s/<sessionId> 反代到对应 bot 的终端代理),因此无端口、对所有 bot 通用

优先级:中心平台 > BOTMUX_PUBLIC_URL > 本地 host:port

改动文件:

  • src/platform/binding.ts:新增纯函数 publicReverseProxyBaseUrl()(读取并归一化 env)
  • src/core/dashboard-url.ts:插入 PUBLIC_URL 兜底;?t= token 保留
  • src/core/terminal-url.ts:同款兜底;平台模式不带 token(平台 SSO 兜底),自建反代保留 token(无 SSO,否则终端裸暴露在域名上)
  • test/{dashboard-url,terminal-url}.test.ts:补用例 + terminal-url 对该 env 做隔离

影响面

  • 纯 opt-in:未设 BOTMUX_PUBLIC_URL 时行为与改动前逐字节一致。
  • 不影响中心平台用户:平台分支优先命中,buildDashboardUrls / buildTerminalUrl 的平台形态完全不变。
  • 仅动公共层 core/dashboard-urlcore/terminal-urlplatform/binding,CLI/后端无关,对所有 bot 一视同仁。
  • webhook 链接未改动:它已按请求 Host 头推导 origin(反代 Host 透传时本就是域名),不需要该 env。

测试验证

  • 单测 test/dashboard-url + test/terminal-url32 全过;terminal-url 在 env 设/空两种条件下均绿(hermetic)。
  • dist 级实测编译产物:
    • 设 env → http://<域名>/s/<id>、写链接 …?token=wtok、dashboard http://<域名>/?t=abc(无 :7891)
    • 不设 env → 回退 http://192.168.28.45:8801/s/…(证明 opt-in、默认不变)
  • live 部署实证:daemon 重启后日志里 4 个会话「Worker ready, terminal at …」全部由 192.168.28.45:88xx 变为 http://<域名>/s/<id>;curl <域名>/s/<id> 返回 200 + <title>Claude…</title>(xterm 页面);使用者在飞书点卡片按钮实测打开终端通过。
  • codex CLI 代码审查通过(仅 1 个 P2 测试隔离问题,已修复并复验)。

🤖 Generated with Claude Code

@xu4wang xu4wang requested a review from deepcoldy as a code owner July 7, 2026 09:24
没接中心平台、但用 nginx 等反代把 dashboard 暴露到单一公网/内网域名的用户,此前
dashboard 链接带 :7891、卡片终端链接甩 per-bot 代理 IP:端口(外网打不开、多 bot 各自
不同端口)。新增环境变量 BOTMUX_PUBLIC_URL(scheme+host[:port]),设了之后 dashboard 链接
与卡片「打开web终端/获取操作链接」统一改吐 <基址>/… 和 <基址>/s/<id>——走 dashboard 前门、
无端口、对所有 bot 通,复用中心平台模式已有的链接翻转逻辑。

改动:
- src/platform/binding.ts: 新增纯函数 publicReverseProxyBaseUrl() 读取并归一化 env(去尾斜杠)
- src/core/dashboard-url.ts: 优先级 平台 > PUBLIC_URL > 本地;token(?t=)保留
- src/core/terminal-url.ts: 同款兜底;平台模式不带 token(平台 SSO 兜底),自建反代必须
  保留 token(无 SSO,否则终端裸暴露)
- test/{dashboard-url,terminal-url}.test.ts: 补 PUBLIC_URL 用例 + terminal-url 对该 env 加
  隔离(顶层 beforeEach 清 env、afterAll 还原),避免 shell 里设了该 env 时污染旧用例

影响面:纯 opt-in——未设 BOTMUX_PUBLIC_URL 时行为与原来逐字节一致;绑定中心平台的用户不受
影响(平台分支优先命中)。仅动公共层 core/terminal-url、core/dashboard-url、platform/binding,
CLI/后端无关,对所有 bot 一视同仁。

测试:
- 单测 dashboard-url + terminal-url 共 32 全过(env 设/空各验一遍,hermetic)
- dist 级实测编译产物:设 env→域名链接(终端读/写带 token、dashboard 无端口);不设→回退本地 IP:端口
- live 部署后日志实证:daemon 重启后 4 个会话「Worker ready」终端 URL 全由 IP 变域名;
  curl 域名 /s/<id> 返回 200+xterm;用户飞书点卡片实测通过
- codex CLI review 通过(仅 1 个 P2 测试隔离问题,已修复复验)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@xu4wang xu4wang force-pushed the feat/public-url-links branch from cb6aecc to 69bb72e Compare July 7, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant