用户诉求:管理端与前端完全分离,本地探针只跑 /admin,前端部署到 GitHub Pages 并硬编码管理地址,探测仍在本地常驻。用户自己搭隧道给本地套 HTTPS。 硬限制(务必先看):GitHub Pages 强制 HTTPS,而浏览器「混合内容」策略禁止 HTTPS 页面 fetch HTTP 资源 —— 这与 CORS 无关,改设置也没用。 因此 settings.dataUrl 必须与面板页面同为 HTTPS。 服务端 - 只读接口(/api/status、/api/monitors、/api/events、/api/v2/getMonitors、 /api/refresh)按 settings.corsOrigins 白名单回显 Access-Control-Allow-Origin - /api/admin/* 一律不放行跨域,预检直接 403 —— 外部页面既读不到也改不了 - 绝不使用 '*':白名单里写 '*' 不放行任何来源 前端 - settings.dataUrl 存在时,所有 api/ 相对路径自动改写到该地址 - 数据源标记为「远程探针(跨域)」,页脚可区分 - 管理界面新增两项配置:跨域数据源地址、允许跨域的页面地址(改完立即生效) 关键设计:origin 匹配必须考虑端口 origin 是「协议 + 主机 + 端口」的完整组合。最初白名单存 http://localhost(无端口), 导致本地前端跑在 localhost:5173 时被拒 —— 浏览器实测 Failed to fetch 而 curl 能过。 修法:回环主机(localhost / 127.0.0.1)忽略端口放行,其余要求完整 origin 精确匹配。 测试:verify-security 25→40 项,新增 [D3] CORS 白名单 14 条 + [D4] '*' 写法 1 条。 全项目 8 套 334 项通过。 附记一个测试上的教训:跨域 fetch 时 JS 读不到 Access-Control-Allow-Origin (CORS 规范规定只有同源能读),所以断言「是否放行」要看 fetch 有没有拿到数据, 不能看响应头 —— 我一开始用 headers.get() 判断,拿到 null 误以为失败。
85 lines
3.8 KiB
HTML
85 lines
3.8 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="description" content="轻量级服务监控面板:HTTP 可用性与 TCP 端口探测">
|
||
<title>Shiroko Monitor</title>
|
||
<link rel="icon" type="image/svg+xml" href="assets/favicon.svg">
|
||
<link rel="stylesheet" href="assets/style.css">
|
||
<link rel="stylesheet" href="assets/theme-shiroko.css">
|
||
</head>
|
||
<body>
|
||
<header class="topbar">
|
||
<div class="brand">
|
||
<span class="logo" aria-hidden="true"></span>
|
||
<div class="brand-text">
|
||
<h1 id="site-title">Shiroko Monitor</h1>
|
||
<p id="site-desc">轻量级服务监控面板</p>
|
||
</div>
|
||
</div>
|
||
<div class="summary">
|
||
<span id="overall-pill" class="pill pending">检测中…</span>
|
||
<div class="stats">
|
||
<div class="stat"><b id="stat-total">–</b><label>监控数</label></div>
|
||
<div class="stat stat-up"><b id="stat-up">–</b><label>在线</label></div>
|
||
<div class="stat stat-down"><b id="stat-down">–</b><label>离线</label></div>
|
||
<div class="stat"><b id="stat-latency">–</b><label>平均延迟</label></div>
|
||
<div class="stat"><b id="stat-uptime">–</b><label>90天可用率</label></div>
|
||
</div>
|
||
<div class="controls">
|
||
<div class="view-switch" id="view-switch" role="group" aria-label="视图切换"></div>
|
||
<button id="theme-btn" type="button" class="icon-btn" title="切换主题">
|
||
<svg viewBox="0 0 100 100" aria-hidden="true">
|
||
<circle cx="50" cy="50" r="31" fill="none" stroke="currentColor" stroke-width="8"/>
|
||
<circle cx="50" cy="50" r="15" fill="none" stroke="currentColor" stroke-width="4" opacity="0.7"/>
|
||
<polygon points="46.4,4 53.6,4 51.2,15 48.8,15" fill="currentColor"/>
|
||
<polygon points="46.4,96 53.6,96 51.2,85 48.8,85" fill="currentColor"/>
|
||
<polygon points="4,46.4 4,53.6 15,51.2 15,48.8" fill="currentColor"/>
|
||
<polygon points="96,46.4 96,53.6 85,51.2 85,48.8" fill="currentColor"/>
|
||
</svg>
|
||
</button>
|
||
<button id="refresh-btn" type="button">刷新</button>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<nav class="group-tabs" id="group-tabs" aria-label="分组筛选"></nav>
|
||
|
||
<main class="grid" id="monitor-grid">
|
||
<div class="empty">正在加载监控配置…</div>
|
||
</main>
|
||
|
||
<!-- 最近事件:故障 / 恢复 / 证书提醒(含维护窗口内的事件) -->
|
||
<section class="events" id="events" hidden>
|
||
<div class="events-head">
|
||
<h2>最近事件</h2>
|
||
<span class="events-count" id="events-count"></span>
|
||
<button type="button" class="events-more" id="events-more" hidden>展开全部</button>
|
||
</div>
|
||
<div class="table-wrap events-wrap">
|
||
<table class="events-table">
|
||
<thead>
|
||
<tr><th>时间</th><th>类型</th><th>目标</th><th>详情</th></tr>
|
||
</thead>
|
||
<tbody id="events-list"></tbody>
|
||
</table>
|
||
</div>
|
||
<p class="events-empty" id="events-empty" hidden>暂无事件记录(故障、恢复与证书提醒会出现在这里)</p>
|
||
</section>
|
||
|
||
<footer class="footer">
|
||
<span id="source-badge" class="footer-item">数据源:–</span>
|
||
<span id="demo-chip" class="footer-item demo-chip" hidden>演示数据</span>
|
||
<span id="ur-chip" class="footer-item warn-chip" hidden>UptimeRobot 同步异常</span>
|
||
<span id="notify-badge" class="footer-item" hidden>通知 –</span>
|
||
<span id="updated-at" class="footer-item">–</span>
|
||
<span id="countdown" class="footer-item">–</span>
|
||
<a id="admin-link" class="footer-item admin-link" hidden>管理</a>
|
||
<span class="footer-item version">shiroko-monitor v0.12.2</span>
|
||
</footer>
|
||
|
||
<script type="module" src="assets/app.js"></script>
|
||
</body>
|
||
</html>
|