Files
certd/packages/ui/certd-server/src/modules/monitor/service/site-tester.ts
T
2025-06-13 00:25:08 +08:00

97 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { logger, safePromise, utils } from "@certd/basic";
import { merge } from "lodash-es";
import https from "https";
import { PeerCertificate } from "tls";
export type SiteTestReq = {
host: string; // 只用域名部分
port?: number;
method?: string;
retryTimes?: number;
ipAddress?: string;
};
export type SiteTestRes = {
certificate?: PeerCertificate;
};
export class SiteTester {
async test(req: SiteTestReq): Promise<SiteTestRes> {
logger.info("测试站点:", JSON.stringify(req));
const maxRetryTimes = req.retryTimes==null ? 3 : req.retryTimes;
let tryCount = 0;
let result: SiteTestRes = {};
while (true) {
try {
result = await this.doTestOnce(req);
return result;
} catch (e) {
tryCount++;
if (tryCount > maxRetryTimes) {
logger.error(`测试站点出错,已超过最大重试次数(${maxRetryTimes}`, e.message);
throw e;
}
//指数退避
const time = 2 ** tryCount;
logger.error(`测试站点出错,${time}s后重试(${tryCount}/${maxRetryTimes})`, e);
await utils.sleep(time * 1000);
}
}
}
async doTestOnce(req: SiteTestReq): Promise<SiteTestRes> {
const options: any = merge(
{
port: 443,
method: "GET",
rejectUnauthorized: false
},
req
);
if (req.ipAddress) {
//使用固定的ip
const ipAddress = req.ipAddress;
options.headers={
host: options.host,
//sni
servername: options.host
}
options.host = ipAddress;
}
options.agent = new https.Agent({ keepAlive: false });
// 创建 HTTPS 请求
const requestPromise = safePromise((resolve, reject) => {
const req = https.request(options, res => {
// 获取证书
// @ts-ignore
const certificate = res.socket.getPeerCertificate();
// logger.info('证书信息', certificate);
if (certificate.subject == null) {
logger.warn("证书信息为空");
resolve({
certificate: null
});
}
resolve({
certificate
});
res.socket.end();
// 关闭响应
res.destroy();
});
req.on("error", e => {
reject(e);
});
req.end();
});
return await requestPromise;
}
}
export const siteTester = new SiteTester();