feat(PingServices): add endpoint and dashboard component for measuring RTT to key services (Google, Cloudflare, Yandex, Instagram)
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m39s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m39s
This commit is contained in:
@@ -309,6 +309,59 @@ function tcpCheck(host, port, timeoutMs) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Измерить RTT (мс) до host:port по TCP. Возвращает число мс или null при ошибке/таймауте. */
|
||||
function measureTcpRtt(host, port = 443, timeoutMs = 6000) {
|
||||
return new Promise((resolve) => {
|
||||
const start = Date.now();
|
||||
const socket = new net.Socket();
|
||||
let settled = false;
|
||||
const settle = (ms) => {
|
||||
if (!settled) {
|
||||
settled = true;
|
||||
try { socket.destroy(); } catch (_) {}
|
||||
resolve(ms);
|
||||
}
|
||||
};
|
||||
socket.setTimeout(timeoutMs, () => settle(null));
|
||||
socket.once('error', () => settle(null));
|
||||
socket.connect(port, host, () => {
|
||||
const ms = Math.round(Date.now() - start);
|
||||
settle(ms);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/** Список целей для пинга с главной: id, имя, хост, порт */
|
||||
const PING_SERVICES = [
|
||||
{ id: 'google', name: 'Google', host: '8.8.8.8', port: 443 },
|
||||
{ id: 'cloudflare', name: 'Cloudflare', host: '1.1.1.1', port: 443 },
|
||||
{ id: 'yandex', name: 'Yandex', host: 'ya.ru', port: 443 },
|
||||
{ id: 'instagram', name: 'Instagram', host: 'instagram.com', port: 443 },
|
||||
];
|
||||
|
||||
// GET /api/ping-services — RTT до Google, Cloudflare, Yandex, Instagram (для карточек на дашборде)
|
||||
async function getPingServices(req, res) {
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
PING_SERVICES.map(async (svc) => {
|
||||
const ms = await measureTcpRtt(svc.host, svc.port, 6000);
|
||||
return { id: svc.id, name: svc.name, host: svc.host, ms };
|
||||
})
|
||||
);
|
||||
const byId = {};
|
||||
results.forEach((r) => { byId[r.id] = r; });
|
||||
res.json(byId);
|
||||
} catch (e) {
|
||||
console.error('ping-services error', e);
|
||||
res.status(500).json({
|
||||
google: { id: 'google', name: 'Google', host: '8.8.8.8', ms: null },
|
||||
cloudflare: { id: 'cloudflare', name: 'Cloudflare', host: '1.1.1.1', ms: null },
|
||||
yandex: { id: 'yandex', name: 'Yandex', host: 'ya.ru', ms: null },
|
||||
instagram: { id: 'instagram', name: 'Instagram', host: 'instagram.com', ms: null },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function anyTrue(promises) {
|
||||
return new Promise((resolve) => {
|
||||
if (!Array.isArray(promises) || promises.length === 0) return resolve(false);
|
||||
@@ -524,5 +577,6 @@ module.exports = {
|
||||
getWsUrl,
|
||||
getUiSettings,
|
||||
postUiSettings,
|
||||
getPingServices,
|
||||
};
|
||||
|
||||
|
||||
@@ -439,6 +439,7 @@ app.post('/api/update-bgp/background', bgpUpdateLimiter, miscRoutes.updateBgpBac
|
||||
app.get('/api/ws/url', miscRoutes.getWsUrl);
|
||||
app.get('/api/ui-settings', miscRoutes.getUiSettings);
|
||||
app.post('/api/ui-settings', miscRoutes.postUiSettings);
|
||||
app.get('/api/ping-services', miscRoutes.getPingServices);
|
||||
|
||||
// === IPSEC PASSWORDS ===
|
||||
app.get('/api/ipsec-passwords', ipsecPasswordsRoutes.getIpsecPasswords);
|
||||
|
||||
Reference in New Issue
Block a user