feat: v0.12.1 —— Worker 支持 UptimeRobot + 管理端远程访问 + 前后端分离

起因:核实「管理端在 Cloudflare 上是否有效」时发现一个更要紧的问题 ——
Worker 完全没有 UptimeRobot 同步能力(runChecks 的探测目标只有 config.monitors)。
而实际配置是 dataFilter=uptimerobot,也就是说直接部署到 Worker 面板会是空的:
它探测 8 个本地条目,而真正在监控的 6 个 UR 目标它根本不认识。

① Worker 支持 UptimeRobot(Step 1)
- edge/cloudflare/uptimerobot.js(新增):Workers 版 UR 只读数据源,
  与 prober/node/lib/uptimerobot.js 同一套语义(状态映射/ratios 解析/故障原因)
- runChecks 的探测集合扩展为「自建目标 + UR 镜像目标」;UR 目标只拉取不探测,
  采用其状态并补齐本地 daily 分桶
- probeScope 与 dataFilter 解耦(与本地探针同语义):config 范围不拉 UR,
  uptimerobot 范围不探测本地
- 同步失败时标记 sources.uptimerobot.ok=false 并保留上次数据,
  绝不把目标判为离线或从面板消失;UR 侧删除的监控自动清理
- 快照新增 probeScope;UR 目标带 meta(面板区分自建/外部)与 uptimeRatios

② 管理端远程访问(Step 2)
- settings.admin.allowRemote:探针默认只监听 127.0.0.1,显式打开才监听全网卡,
  启动日志就此告警。这是 Cloudflare Tunnel 的安全前提(已实测两种行为)
- edge/cloudflare/tunnel.yml(新增):命名隧道配置,只放行
  ^/(admin|api/admin/.*|assets/.*)$,其余 404 —— 不把公开面板一起挂到公网

③ 前后端分离(Step 3)
- Worker 侧 /admin 与 /api/admin/* 显式返回 403 + 指向文档的提示,
  而非默默落到静态资源变成 404,确保边缘侧没有任何可写面

测试:新增 scripts/verify-worker.cjs(36 项)—— 把 Worker 以 data: URL 动态载入以
绕开 cloudflare:sockets,注入假 KV/静态资源/UptimeRobot 服务器,
不需要 wrangler 也不需要联网。全项目 8 套 310 项全部通过。

过程中抓到两个真 bug:
1. UR 同步失败的降级路径引用了不含 meta 的旧对象,导致 name/url 为 undefined、
   UR 目标从面板上消失
2. stats.total 按 config.monitors.length 计数,在 probeScope=uptimerobot 时
   与实际参与的目标数不符

另有一条测试夹具教训:内存版 KV 必须实现 get(key, 'json') 的类型参数
(真实 Workers KV 会自动反序列化),否则 state.monitors 恒为 undefined。
This commit is contained in:
tamakyi
2026-10-14 14:51:28 +08:00
parent 752fad412b
commit d2aa0a1163
11 changed files with 1013 additions and 331 deletions
+15 -2
View File
@@ -39,7 +39,7 @@ const CONCURRENCY = 8;
const WRITE_DEBOUNCE_MS = 300;
const DEFAULT_INTERVAL_SEC = 60;
const PORT = Number(process.env.PORT || 8787);
const VERSION = '0.12.0';
const VERSION = '0.12.1';
const UR_DEFAULT_POLL_SEC = 300;
const UR_MIN_REFRESH_GAP_MS = 60000;
@@ -1120,7 +1120,13 @@ async function main() {
}
}, 1000);
createServer(runtime).listen(PORT, () => {
// 管理端是否允许经由非本机地址访问(如 Cloudflare Tunnel 挂到公网)。
// 默认关闭:探针通常只该在内网/本机使用,暴露管理面必须由使用者显式打开。
const adminCfg = runtime.config.settings?.admin ?? {};
const adminPublic = adminCfg.allowRemote === true;
const BIND_HOST = adminPublic ? '0.0.0.0' : '127.0.0.1';
createServer(runtime).listen(PORT, BIND_HOST, () => {
console.log(`shiroko-monitor v${VERSION}`);
console.log(`面板: http://localhost:${PORT}/`);
console.log(`状态 API: http://localhost:${PORT}/api/status`);
@@ -1136,6 +1142,13 @@ async function main() {
if (!localCount && !runtime.ur.enabled) {
console.warn('[warn] 当前没有任何数据源:本地探测已关闭且 UptimeRobot 未启用,面板将显示「等待检测」');
}
if (adminPublic) {
console.log(`管理后台: http://localhost:${PORT}/admin`);
console.warn(`[warn] settings.admin.allowRemote=true —— 探针正在监听 ${BIND_HOST},管理端可经由反向代理/隧道从外部访问。`);
console.warn(' 该端口同时伺服公开面板,请确保管理端已绑定 2FA,且前置代理已启用 HTTPS。');
} else {
console.log(`管理后台: http://localhost:${PORT}/admin (仅本机可访问;需远程访问请设 settings.admin.allowRemote=true)`);
}
});
}