feat(PingServices): add endpoint for retrieving ping services list and update dashboard to display dynamic service configurations
Publish Fast Tabler Docker image / build-and-push-fast (push) Failing after 1m12s
Publish Fast Tabler Docker image / build-and-push-fast (push) Failing after 1m12s
This commit is contained in:
@@ -331,14 +331,29 @@ function measureTcpRtt(host, port = 443, timeoutMs = 6000) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Список целей для пинга с главной: 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 },
|
||||
/** Список целей для пинга по умолчанию (id, name, host, port, icon, color) */
|
||||
const PING_SERVICES_DEFAULT = [
|
||||
{ id: 'google', name: 'Google', host: '8.8.8.8', port: 443, icon: 'IconBrandGoogle', color: 'blue' },
|
||||
{ id: 'cloudflare', name: 'Cloudflare', host: '1.1.1.1', port: 443, icon: 'IconBrandCloudflare', color: 'orange' },
|
||||
{ id: 'yandex', name: 'Yandex', host: 'ya.ru', port: 443, icon: 'IconBrandYandex', color: 'red' },
|
||||
{ id: 'instagram', name: 'Instagram', host: 'instagram.com', port: 443, icon: 'IconBrandInstagram', color: 'pink' },
|
||||
];
|
||||
|
||||
function getPingServicesListFromSettings(uiSettings) {
|
||||
const raw = uiSettings.pingServicesList;
|
||||
if (Array.isArray(raw) && raw.length > 0) {
|
||||
return raw.map((s) => ({
|
||||
id: String(s?.id ?? '').trim() || `svc-${Math.random().toString(36).slice(2, 9)}`,
|
||||
name: String(s?.name ?? '').trim() || 'Сервис',
|
||||
host: String(s?.host ?? '').trim() || '0.0.0.0',
|
||||
port: Math.max(1, parseInt(s?.port, 10) || 443),
|
||||
icon: typeof s?.icon === 'string' ? s.icon : 'IconWorld',
|
||||
color: typeof s?.color === 'string' ? s.color : 'primary',
|
||||
})).filter((s) => s.host !== '0.0.0.0');
|
||||
}
|
||||
return PING_SERVICES_DEFAULT;
|
||||
}
|
||||
|
||||
/** Загрузить UI-настройки из S3 (для pingServicesSource и др.) */
|
||||
async function loadUiSettingsSync() {
|
||||
try {
|
||||
@@ -353,16 +368,26 @@ async function loadUiSettingsSync() {
|
||||
|
||||
const PING_SERVICES_CACHE_KEY_PREFIX = 'ping-services/cache_';
|
||||
|
||||
// GET /api/ping-services — RTT до Google, Cloudflare, Yandex, Instagram (веб или через RouterOS по настройке)
|
||||
async function getPingServices(req, res) {
|
||||
const fallbackPayload = {
|
||||
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 },
|
||||
};
|
||||
// GET /api/ping-services-list — список сервисов для пинга из настроек (для дашборда и редактора)
|
||||
async function getPingServicesList(req, res) {
|
||||
try {
|
||||
const uiSettings = await loadUiSettingsSync();
|
||||
const list = getPingServicesListFromSettings(uiSettings);
|
||||
return res.json({ list });
|
||||
} catch (e) {
|
||||
console.error('ping-services-list error', e);
|
||||
return res.json({ list: PING_SERVICES_DEFAULT });
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/ping-services — RTT до сервисов из списка (веб или через RouterOS по настройке)
|
||||
async function getPingServices(req, res) {
|
||||
try {
|
||||
const uiSettings = await loadUiSettingsSync();
|
||||
const servicesList = getPingServicesListFromSettings(uiSettings);
|
||||
const fallbackPayload = {};
|
||||
servicesList.forEach((s) => { fallbackPayload[s.id] = { id: s.id, name: s.name, host: s.host, ms: null }; });
|
||||
|
||||
const viaRouter = String(uiSettings.pingServicesSource || 'web').toLowerCase() === 'router';
|
||||
const cacheSeconds = Math.max(0, parseInt(uiSettings.pingServicesCacheSeconds, 10) || 0);
|
||||
|
||||
@@ -414,7 +439,7 @@ async function getPingServices(req, res) {
|
||||
return res.json(fallbackPayload);
|
||||
}
|
||||
const results = await Promise.all(
|
||||
PING_SERVICES.map(async (svc) => {
|
||||
servicesList.map(async (svc) => {
|
||||
try {
|
||||
const result = await runPingViaRouter(serverId, gatewayIpResolved || null, svc.host, 3);
|
||||
const ms = typeof result.avgMs === 'number' ? Math.round(result.avgMs) : null;
|
||||
@@ -434,7 +459,7 @@ async function getPingServices(req, res) {
|
||||
}
|
||||
|
||||
const results = await Promise.all(
|
||||
PING_SERVICES.map(async (svc) => {
|
||||
servicesList.map(async (svc) => {
|
||||
const ms = await measureTcpRtt(svc.host, svc.port, 6000);
|
||||
return { id: svc.id, name: svc.name, host: svc.host, ms };
|
||||
})
|
||||
@@ -447,7 +472,9 @@ async function getPingServices(req, res) {
|
||||
res.json(byId);
|
||||
} catch (e) {
|
||||
console.error('ping-services error', e);
|
||||
res.status(500).json(fallbackPayload);
|
||||
const fallback = {};
|
||||
PING_SERVICES_DEFAULT.forEach((s) => { fallback[s.id] = { id: s.id, name: s.name, host: s.host, ms: null }; });
|
||||
res.status(500).json(fallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,6 +693,7 @@ module.exports = {
|
||||
getWsUrl,
|
||||
getUiSettings,
|
||||
postUiSettings,
|
||||
getPingServicesList,
|
||||
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-list', miscRoutes.getPingServicesList);
|
||||
app.get('/api/ping-services', miscRoutes.getPingServices);
|
||||
|
||||
// === IPSEC PASSWORDS ===
|
||||
|
||||
Reference in New Issue
Block a user