已实现:HTTP/TCP/Banner 探测、90 天可用率、表格/卡片视图、 数据源过滤、UptimeRobot 双向兼容、服务端驱动的刷新节奏、 刷新接口滥用防护与信息泄露控制。
32 lines
1.2 KiB
JavaScript
32 lines
1.2 KiB
JavaScript
const USER_AGENT = 'shiroko-monitor/0.2 (lightweight uptime panel)';
|
||
|
||
export async function probeHttp(monitor) {
|
||
const started = Date.now();
|
||
const timeoutMs = (monitor.timeout ?? 10) * 1000;
|
||
try {
|
||
// redirect: manual —— 保留 3xx 原始状态码交给 expectStatus 判定,避免跟随重定向掩盖异常
|
||
const res = await fetch(monitor.url, {
|
||
method: monitor.method || 'GET',
|
||
redirect: 'manual',
|
||
signal: AbortSignal.timeout(timeoutMs),
|
||
headers: { 'user-agent': USER_AGENT, accept: '*/*' },
|
||
});
|
||
const latency = Date.now() - started;
|
||
const expect = monitor.expectStatus ?? [200];
|
||
const ok = expect.includes(res.status);
|
||
return {
|
||
status: ok ? 'up' : 'down',
|
||
latency,
|
||
code: res.status,
|
||
detail: ok ? `HTTP ${res.status}` : `HTTP ${res.status}(期望 ${expect.join('/')})`,
|
||
};
|
||
} catch (err) {
|
||
const latency = Date.now() - started;
|
||
let detail;
|
||
if (err.name === 'TimeoutError') detail = `请求超时(>${timeoutMs / 1000}s)`;
|
||
else if (err.cause?.code) detail = err.cause.code;
|
||
else detail = err.message;
|
||
return { status: 'down', latency, code: 0, detail };
|
||
}
|
||
}
|