feat(MikrotikConfig, NetworkConfigManager): implement streaming logs for MikroTik configuration application and enhance error handling in response processing
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 3m2s
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 3m2s
This commit is contained in:
@@ -2237,16 +2237,53 @@ function NetworkConfigManager() {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-Stream-Logs': '1',
|
||||
},
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
console.log('[MikroTik apply] Response:', { status: response.status, ok: response.ok, url: response.url });
|
||||
|
||||
const data = await response.json().catch((parseErr) => {
|
||||
console.warn('[MikroTik apply] JSON parse error:', parseErr);
|
||||
return {};
|
||||
});
|
||||
const contentType = response.headers.get('Content-Type') || '';
|
||||
const isStream = contentType.includes('ndjson') || contentType.includes('x-ndjson');
|
||||
|
||||
let data = {};
|
||||
if (isStream && response.body) {
|
||||
const reader = response.body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = '';
|
||||
let finalData = null;
|
||||
while (true) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) break;
|
||||
buffer += decoder.decode(value, { stream: true });
|
||||
const lines = buffer.split('\n');
|
||||
buffer = lines.pop() || '';
|
||||
for (const line of lines) {
|
||||
if (!line.trim()) continue;
|
||||
try {
|
||||
const obj = JSON.parse(line);
|
||||
if (obj.t === 'log') {
|
||||
console.log('[MikroTik apply]', obj.msg, obj);
|
||||
} else if (obj.t === 'result') {
|
||||
finalData = obj;
|
||||
} else if (obj.t === 'error') {
|
||||
finalData = { ok: false, error: obj.error, mikrotikRequests: obj.mikrotikRequests };
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
if (buffer.trim()) {
|
||||
try {
|
||||
const obj = JSON.parse(buffer);
|
||||
if (obj.t === 'result') finalData = obj;
|
||||
else if (obj.t === 'error') finalData = { ok: false, error: obj.error, mikrotikRequests: obj.mikrotikRequests };
|
||||
} catch (_) {}
|
||||
}
|
||||
data = finalData || {};
|
||||
} else {
|
||||
data = await response.json().catch(() => ({}));
|
||||
}
|
||||
|
||||
if (!response.ok || data.ok === false) {
|
||||
const errorMessage = data.error || data.message || `HTTP ${response.status}`;
|
||||
@@ -2257,21 +2294,18 @@ function NetworkConfigManager() {
|
||||
}
|
||||
|
||||
console.log('[MikroTik apply] Success:', data);
|
||||
if (data.mikrotikRequests?.length) {
|
||||
console.log('[MikroTik apply] Запросы к MikroTik:', data.mikrotikRequests);
|
||||
}
|
||||
setApplyResult(data);
|
||||
|
||||
if (data.ok && !useDryRun) {
|
||||
notify.success(`Применено: создано ${data.summary?.created || 0}, обновлено ${data.summary?.updated || 0}, пропущено ${data.summary?.skipped || 0}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[MikroTik apply] Fetch failed:', error);
|
||||
const url = `${window.location.origin}/api/mikrotik/apply`;
|
||||
console.error('[MikroTik apply] Fetch failed:', error, '\nURL:', url);
|
||||
const errMsg = error.message || 'Ошибка применения';
|
||||
const hint = errMsg.includes('fetch') || errMsg.includes('Failed') ? ' Проверьте логи backend — при ERR_EMPTY_RESPONSE сервер мог не ответить.' : '';
|
||||
setApplyResult({
|
||||
ok: false,
|
||||
error: errMsg + hint,
|
||||
error: errMsg + ` Сеть: ${url}`,
|
||||
});
|
||||
notify.error('Не удалось применить конфигурацию по API');
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user