Glowing Bear 0.10.0 嵌入与集成使用详解

Glowing Bear 0.10.0 嵌入与集成使用详解:WeeChat relay 协议握手要点(handshake/init/pbkdf2 实测)、iframe 嵌入自家页面实测、多客户端并发与 max_clients 拒绝实测、移动端窄屏布局实测、断连重连与排障全记录,全部场景实测验证。

Glowing Bear即时通讯IRCWebSocket2026/10/26

Glowing Bear 0.10.0 嵌入与集成使用详解

目标:把 Glowing Bear 0.10.0 用出部署之外的花样——读懂它对外的唯一接口(WeeChat relay 协议)、把它嵌进自家页面、跑多端并发、适配手机窄屏、并在断连时知道去哪排障。所有场景均在 Ubuntu 22.04 + WeeChat 3.5 + nginx 环境实测通过(2026-10-26)。

一、环境信息

项目值
操作系统Ubuntu 22.04.5 LTS,x86_64
WeeChat3.5-1,relay 9001(明文)/ 9002(TLS),relay: listening on port 9001 (relay: weechat, IPv4+6, max 5 clients)
Glowing Bear0.10.0(master commit b53e42f5),nginx 1.18.0 静态托管 + /weechat WebSocket 反代
浏览器实测工具Chromium 无头浏览器 + Node.js WebSocket 脚本(复刻前端握手)
对端 IRC 客户端同频道另一 IRC 客户端(peer,用于收发回声验证)
演示 relay 密码q1w2e3r4

前置条件:已按《Ubuntu 22.04 部署 Glowing Bear 指南》( https://www.quzuo.net/document/f16RyM65090X )完成部署,浏览器可连上 WeeChat 并收发频道消息。

二、relay 协议要点(集成的唯一接口)

Glowing Bear 没有自己的服务端 API——它对外的"集成接口"就是 WeeChat relay 协议本身(WebSocket)。理解握手流程,就能用任何语言写自己的客户端,也能读懂前端的连接问题。

接入端点:ws://<relay>:9001(明文)或 wss://<relay>:9002(TLS relay)或 wss://<站点>/weechat(nginx 反代,推荐——同源、证书复用、对外只暴露 443)。

三步握手(实测脚本逐步复刻 Glowing Bear 的行为,回显为脚本与 relay 侧真实交互):

第 1 步,WebSocket 打开后,客户端先发握手行(声明支持的哈希算法与压缩):

>>> handshake compression=off,password_hash_algo=pbkdf2+sha512

relay 回应一行握手参数(含 16 字节 nonce、协商出的算法与迭代次数):

<<< handshake password_hash_algo=pbkdf2+sha512,nonce=<32位hex>,password_hash_iterations=100000

第 2 步,客户端按 salt = nonce + ":" + client_nonce 拼盐,做 PBKDF2-HMAC-SHA512(64 字节、迭代次数取服务端返回值),发 init 行:

>>> init password_hash=pbkdf2+sha512:<salt-hex>:100000:<hash-hex>

认证通过后 relay 侧日志(WeeChat 核心 buffer 实测原文):

relay: new client on port 9001: 1/weechat/127.0.0.1 (waiting auth)
relay: websocket client
relay: client 1/weechat/127.0.0.1 has real IP address "10.89.73.1"
relay: client 1/weechat/127.0.0.1 connected/authenticated

第 3 步,发带 id 的命令获取数据,relay 以二进制消息回数据(成功处理后续消息体为 W3C zlib 压缩,Glowing Bear 依赖 zlibjs 解包):

(1) info version
(2) hdata buffer:gui_buffers(*) number,full_name,short_name,title,type
(3) input core.weechat /help

要点速记:

  • 命令首行 (id) 指令 的 id 会原样出现在响应里,用于请求-响应配对;
  • 数据面是 hdata(buffer/line/nick 等结构)与 info/infolist(标量信息),前端首屏即用第 2 类命令拉全量 buffer 列表;
  • 写入用 input <buffer全名> <命令/消息>,Glowing Bear 输入框发送的就是它;
  • 密码错误/超时的表现为连接被 relay 主动关闭,日志停在 waiting auth。

💡 说明:Glowing Bear 官方 FAQ 明确不建议把 relay 连接中转到别的后端("that's not what Glowing Bear does"),官方认可的集成路径是:浏览器直连 relay,或用 Web 服务器的 websocket proxy 把 /weechat 转发到 relay(官方 wiki 有专页)。本文的嵌入方案均不引入中间服务。

三、嵌入自家页面:iframe 集成实测

Glowing Bear 是自包含静态应用,可直接用 iframe 嵌入自家门户。实测宿主页(标题"公司内部门户 - 嵌入式 IRC"):

<!doctype html>
<html lang="zh">
<head><meta charset="utf-8"><title>公司内部门户 - 嵌入式 IRC</title></head>
<body style="margin:0;height:100vh;display:flex;flex-direction:column">
  <header style="height:40px">…门户导航…</header>
  <iframe src="https://<站点>/"
          style="flex:1;border:0;width:100%"
          allow="clipboard-write"></iframe>
</body>
</html>

实测结果(无头浏览器断言 + 截图,2026-10-26 08:39):子框架内完整渲染出 Glowing Bear 工作台——buffer 列表 weechat / local / #test / relay.relay.list、消息区、底部输入框 textarea#sendMessage 均在 iframe 内可用,连接状态正常。嵌入注意事项实测归纳:

  1. 同源最优:宿主页与 iframe 同域(同协议+域名+端口)时无跨域摩擦。跨域嵌入时 iframe 内 localStorage(密码存储)仍归属 iframe 自身域,功能不受影响,但宿主页无法读取 iframe 内部状态(这是浏览器边界,不是缺陷)。
  2. 不要嵌连接页参数劫持:连接参数(host/port/password/TLS/TOTP)保存在前端 localStorage,iframe 里首次仍需手动填一次;自动连接勾选后,之后打开门户即自动进入工作台。
  3. 高度要给足:Glowing Bear 布局依赖视口高度(侧栏 + 消息区 + 输入条),iframe 容器按 height:100%/flex 撑满,否则消息区被压扁。
  4. X-Frame-Options:Glowing Bear 静态托管默认不发 X-Frame-Options/frame-ancestors,可被任意页面嵌;若站点由你自管 nginx,可按需加 Content-Security-Policy: frame-ancestors 'self' https://portal.example.com 收紧被嵌白名单。
  5. WebSocket 走同源反代:iframe 内前端连 wss://<站点>/weechat 与宿主页同域,混合内容告警为零;若 iframe 指向 http 站点而宿主是 https,浏览器直接拦截——宿主 https 则 iframe 必须也是 https。

另一种"嵌入"是 PWA 形态:官方 README 给出的路径——桌面 Chrome "Tools → Create application shortcuts" 建独立窗口;安卓 Chrome 菜单 "Add to homescreen" 得到全屏应用(无浏览器地址栏,体验接近原生 App)。

四、多端与多 buffer 场景实测

4.1 多客户端并发与 max_clients 拒绝

用脚本按 relay 握手流程同时开 6 个客户端连 9001(relay.network.max_clients 默认 5),实测每连接一行脚本输出,relay 侧同步记日志。脚本判定输出:

client 1 => CONNECTED
client 2 => CONNECTED
client 3 => CONNECTED
client 4 => CONNECTED
client 5 => CONNECTED
client 6 => REJECTED (close 1006)
SUM connected=5 rejected=1

relay 侧对应日志(WeeChat 核心 buffer 实测原文,注意第 6 个连入触发的连锁断开):

relay: client 5/weechat/127.0.0.1 connected/authenticated
=!=  relay: client not allowed (max 5 clients are allowed at same time)
relay: disconnected from client 1/weechat/127.0.0.1
relay: disconnected from client 2/weechat/127.0.0.1
relay: disconnected from client 3/weechat/127.0.0.1
relay: disconnected from client 4/weechat/127.0.0.1
relay: disconnected from client 5/weechat/127.0.0.1
relay: no connected client for relay

结论:默认 5 上限下"第 6 个连入导致全体断开",多端场景(电脑 + 手机 + iframe 门户 + 脚本监控)应调大:/set relay.network.max_clients 10 后 /save。

4.2 多 buffer 视图与 relay 自省 buffer

连接成功后前端侧栏按 WeeChat buffer 全量渲染,实测列表:weechat(核心)、local(IRC 服务器)、#test(频道)、relay.relay.list(relay 自省 buffer)。两个使用点:

  • buffer 列表即 WeeChat 侧 buffer 镜像:在 WeeChat 里 /join #new 前端立即多出该项;关闭某 buffer 侧栏同步消失(/close)。
  • relay.relay.list 是 relay 插件的自省 buffer:前端里点开可直接看 relay 实例与状态,无需 SSH。

多端一致性实测:桌面端与无头浏览器同时在线时,#test 频道发送 hello-from-glowing-bear,两个端都实时收到同一消息与 peer 回声 hello-from-irc;短时断开的一端重连后按 backlog 补放(频道顶部出现 ========== End of backlog (18 lines) ========== 边界行),不丢不重。

五、移动端使用实测

以窄视口(约 715px 宽,对应手机竖屏)加载站点,实测布局(截图断言):

  • 顶栏压缩为"熊头图标 + 未读角标(1)+ 当前 buffer 名 + 设置/断开按钮";
  • 侧栏 buffer 列表与消息区并存,消息区自适应宽度换行;
  • 底部输入条保留:表情、图片、发送三键齐全,textarea 自动聚焦弹出软键盘;
  • 未读消息在 buffer 名右侧以数字角标标记(截图 #test 显示 1)。

使用建议:手机端推荐两种入口——直接浏览器收藏 https://<站点>/(勾选 Save Password + Automatically connect),或安卓 Chrome "Add to homescreen" 全屏 PWA。relay 侧无需任何手机特配;若手机走移动网络,务必 HTTPS(反代 443 或直连 9002 TLS relay)。

六、断连重连与排障实测

断连表现:relay 连接被切断时,前端顶部弹出红色横幅(实测原文,注意官方把 Reconnecting 拼作 "Reconnecting"):

Connection to WeeChat lost
Reconnecting… ↻ Click to try to reconnect now

自动重连:横幅出现后前端自动重试;实测采样(无头浏览器按 9 秒后首采、之后每 3 秒一次共 12 次)期间 relay 日志记录了至少 4 轮 new client → waiting auth → connected/authenticated,即前端在断开后持续自动重连并最终恢复,无需人工点击。relay 侧断开原因实测:

relay: reading data on socket for client 1/weechat/127.0.0.1: error 4 (connection closed by peer)

恢复后状态:buffer 列表、当前 buffer、未读角标原样保留;频道消息按 backlog_since_last_disconnect = on 补放断开期间的消息(默认上限 backlog_max_number = 1024)。

排障速查(按现象定位侧别):

现象定位依据
停在 "Connecting…"网络/TLS/反代层浏览器 WS 面板无 101;查 nginx proxy_read_timeout、relay ss -ltn
反复弹 "Connection to WeeChat lost"反代空闲超时或 relay 拒绝nginx 默认 60s 断连 → 调 3600s;或 max_clients 满被断
连上即要求重新输密码认证层relay 日志停在 waiting auth;核对 password/TOTP
恢复后消息重复刷屏backlog 基准backlog_since_last_disconnect 应为 on(默认)
手机流量下频繁断中间网络掐长连确认走 443 反代且 proxy_read_timeout 足够大

七、注意事项

  • 不要给 relay 加中间服务:官方 FAQ 明确 Glowing Bear 不做连接中转;集成路径只有浏览器直连与 Web 服务器 WebSocket 反代两条。
  • 多端预算 max_clients:电脑浏览器 + 手机 + iframe 门户 + 脚本监控,每条 WebSocket 各占一个名额,默认 5 很容易触顶,且触顶是"全员断开"(见 4.1 实测)。
  • iframe 跨协议必挂:https 宿主页嵌 http 前端会被浏览器拦;两端协议与证书必须一致。
  • relay 端口收权:集成面越大越要收紧 relay——bind_address 限内网、websocket_allowed_origins 限本站、公网只暴露 443(参数详解见本专栏《Glowing Bear 0.10.0 配置参数详解》( https://www.quzuo.net/document/z5EZ9mEpGXDG ))。
  • 升级前端时锁定 commit:官方无正式 Release,自托管升级建议 git fetch && git checkout <commit> 后重新 npm run build,避免 blind 更新把连接页行为带偏。

八、常见问题(FAQ)

Q1:能不能用 Glowing Bear 把公司内网的 WeeChat 转发给外网同事? 不能按"转发"思路用(官方 FAQ 原话:"No, that's not what Glowing Bear does")。正确形态:nginx 反代 + HTTPS 把 relay 安全暴露,前端静态文件托管在哪都不影响连接走向(浏览器直连 relay)。

Q2:iframe 嵌入后想自动连上,还要每次输密码吗? 不用。连接页勾选 Save Password 与 Automatically connect,参数存 iframe 自己的 localStorage,之后打开门户自动进入工作台(首次必须手动连一次)。

Q3:手机和电脑能同时收消息吗? 能,前提 max_clients 足够(默认 5;多端建议调到 10)。两端正/离线互不影响,离线端重连后按 backlog 补放。

Q4:想自己写个监控脚本抓频道消息,从哪下手? 复用 relay 协议即可:WebSocket 连 relay → 三步握手(见第二章)→ (id) hdata buffer:gui_buffers(*) … 拉 buffer → 订阅 line 更新。本文实测脚本即按此流程通过(脚本复刻 handshake/init/命令 id 全流程)。

Q5:断线横幅一直转圈连不上怎么办? 看 relay 日志三分:无 new client → 网络/反代层不通;停在 waiting auth → 密码/TOTP 问题;client not allowed (max …) → 调大 max_clients。

九、参考链接