feat(MikrotikConfigRoutes): add logging for address list requests and responses to improve debugging
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 1m52s

This commit is contained in:
2026-02-21 18:47:21 +07:00
parent c3c30b1c75
commit dfbd38d9a3
+60 -3
View File
@@ -1146,6 +1146,42 @@ async function runScript(req, res) {
}
}
/** Логирование в контейнер: JSON запроса/ответа и эквивалент CLI MikroTik */
function logAddressListRequest(creds, method, path, query) {
const protocol = creds.secure ? 'https' : 'http';
const url = `${protocol}://${creds.host}:${creds.port}/rest/${path}${query ? `?${query}` : ''}`;
const cli = '/ip firewall address-list print';
const payload = { component: 'address-lists', request: { method, path, url, cli } };
console.log(JSON.stringify(payload));
console.log(`[address-lists] MikroTik CLI: ${cli}`);
}
function logAddressListResponse(raw, listRawLength, banCount, banCounterCount) {
const firstKeys = Array.isArray(raw) && raw[0] && typeof raw[0] === 'object'
? Object.keys(raw[0])
: (raw && typeof raw === 'object' && !Array.isArray(raw) ? Object.keys(raw) : []);
let rawSnippet;
try {
const s = JSON.stringify(raw);
rawSnippet = s.length > 800 ? s.slice(0, 800) + '...' : s;
} catch (_) {
rawSnippet = String(raw);
}
const payload = {
component: 'address-lists',
response: {
rawIsArray: Array.isArray(raw),
rawLength: Array.isArray(raw) ? raw.length : undefined,
listRawLength: listRawLength,
banCount,
banCounterCount,
firstItemKeys: firstKeys,
rawSnippet: rawSnippet?.slice(0, 600),
},
};
console.log(JSON.stringify(payload));
}
/**
* GET /api/mikrotik/address-lists?serverId=xxx
* Возвращает address-list списки ban и ban_counter с выбранного роутера (MikroTik).
@@ -1171,8 +1207,26 @@ async function getAddressLists(req, res) {
const client = createRosClient(creds);
const path = 'ip/firewall/address-list';
// REST API не всегда поддерживает фильтр по list — загружаем все и фильтруем по полю list
logAddressListRequest(creds, 'GET', path, '');
let all = await rosPrint(client, path);
if (!Array.isArray(all) || all.length === 0) {
logAddressListRequest(creds, 'POST', `${path}/print`, '');
try {
const postRes = await client.command(`${path}/print`, {});
const data = postRes?.data;
if (data && typeof data === 'object' && Array.isArray(data.ret)) {
all = data.ret;
} else if (Array.isArray(data)) {
all = data;
} else if (data && typeof data === 'object') {
all = Array.isArray(data) ? data : [data];
}
} catch (postErr) {
console.error(JSON.stringify({ component: 'address-lists', postFallbackError: postErr?.message || String(postErr) }));
}
}
if (Array.isArray(all) && all.length === 1 && all[0] && typeof all[0] === 'object' && Array.isArray(all[0].ret)) {
all = all[0].ret;
} else if (all && typeof all === 'object' && !Array.isArray(all) && Array.isArray(all.ret)) {
@@ -1180,15 +1234,18 @@ async function getAddressLists(req, res) {
}
const listRaw = Array.isArray(all) ? all : [];
// Имя списка: RouterOS REST отдаёт "list" (или "List"), возможен kebab "address-list"
const getListName = (entry) => {
if (!entry || typeof entry !== 'object') return '';
const name = entry.list ?? entry.List ?? '';
const name = entry.list ?? entry.List ?? entry['address-list'] ?? '';
return String(name).trim().toLowerCase();
};
const ban = listRaw.filter((e) => getListName(e) === 'ban');
const banCounter = listRaw.filter((e) => getListName(e) === 'ban_counter');
logAddressListResponse(all, listRaw.length, ban.length, banCounter.length);
return sendOk(res, {
serverId,
serverLabel: server.dns || server.ip || serverId,
@@ -1198,7 +1255,7 @@ async function getAddressLists(req, res) {
} catch (error) {
const msg = error.response?.data?.detail || error.response?.data?.message || error.message || 'Ошибка получения address-list';
const status = error.response?.status;
console.error('getAddressLists:', error);
console.error(JSON.stringify({ component: 'address-lists', error: msg, stack: error?.stack }));
return sendError(res, status && status >= 400 ? status : 502, msg, 'E_ADDRESS_LISTS');
}
}