65 lines
3.1 KiB
TypeScript
65 lines
3.1 KiB
TypeScript
import chalk from "chalk";
|
|
|
|
type CheckTarget = [url: string, expectedStatus: number | ((status: number) => boolean)];
|
|
|
|
export async function testNetwork() {
|
|
const targets: CheckTarget[] = [
|
|
["https://www.baidu.com", 200],
|
|
["http://www.google.com", (s) => s === 200 || (s >= 300 && s < 400)], // 某些环境会被重定向
|
|
["https://www.google.com", (s) => s === 200 || (s >= 300 && s < 400)],
|
|
[process.env.OPENAI_BASE_URL || "https://api.openai.com/v1", (s) => s === 200 || (s >= 300 && s < 400) || s === 401 || s === 403 || s === 404 || s === 421], // 允许常见网关/鉴权返回
|
|
|
|
];
|
|
|
|
const results: Array<{ url: string; status?: number; ok: boolean; error?: string }> = [];
|
|
|
|
console.log(chalk.cyan("\n[Network] 开始健康检查..."));
|
|
|
|
for (const [url, expected] of targets) {
|
|
const label = chalk.white(url);
|
|
try {
|
|
const controller = new AbortController();
|
|
const timeoutMs = 5000;
|
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
const start = Date.now();
|
|
const res = await fetch(url, { method: "GET", signal: controller.signal });
|
|
const cost = Date.now() - start;
|
|
clearTimeout(timeoutId);
|
|
|
|
const status = res.status;
|
|
const pass = typeof expected === "function" ? expected(status) : status === expected;
|
|
|
|
results.push({ url, status, ok: pass });
|
|
|
|
const statusStr = pass
|
|
? chalk.green.bold(String(status))
|
|
: chalk.red.bold(String(status));
|
|
const costStr = cost >= 1000 ? `${(cost / 1000).toFixed(2)}s` : `${cost}ms`;
|
|
|
|
if (pass) {
|
|
console.log(`${chalk.green("✔ PASS")} ${label} ${chalk.gray("- status:")} ${statusStr} ${chalk.gray("latency:")} ${chalk.blue(costStr)}`);
|
|
} else {
|
|
const expectedStr = typeof expected === "function" ? "custom" : String(expected);
|
|
console.log(`${chalk.red("✖ FAIL")} ${label} ${chalk.gray("- status:")} ${statusStr} ${chalk.gray("expected:")} ${chalk.yellow(expectedStr)} ${chalk.gray("latency:")} ${chalk.blue(costStr)}`);
|
|
}
|
|
} catch (error) {
|
|
const isTimeout = (error as any)?.name === "AbortError";
|
|
const msg = isTimeout ? "timeout" : (error as any)?.message || String(error);
|
|
results.push({ url, ok: false, error: msg });
|
|
console.log(`${chalk.red("✖ ERROR")} ${label} ${chalk.gray("- ")} ${chalk.red(isTimeout ? "请求超时" : msg)}`);
|
|
}
|
|
}
|
|
|
|
// 汇总
|
|
const passed = results.filter(r => r.ok).length;
|
|
const failed = results.length - passed;
|
|
const timeoutCount = results.filter(r => r.error === "timeout").length;
|
|
|
|
const summary = [
|
|
`${chalk.green(`${passed} passed`)}`,
|
|
`${failed ? chalk.red(`${failed} failed`) : chalk.gray(`${failed} failed`)}`,
|
|
`${timeoutCount ? chalk.yellow(`${timeoutCount} timeout`) : chalk.gray(`${timeoutCount} timeout`)}`,
|
|
].join(chalk.gray(" | "));
|
|
|
|
console.log(chalk.cyan("[Network] 健康检查完成:"), summary, "\n");
|
|
} |