- Добавлен CORSMiddleware в app.py для решения проблем с CORS - Создан test_api.py для тестирования API endpoints - Создан test_websocket.py для тестирования WebSocket соединений - Создан test_browser.html для тестирования в браузере - Все тесты показывают, что API и WebSocket работают корректно Диагностика показала: ✅ API endpoints работают (health, auth, containers, logs) ✅ WebSocket соединения работают и передают логи ✅ Проблема может быть в браузере или localStorage Для тестирования в браузере: 1. Откройте http://localhost:9001/test_browser.html 2. Выполните тесты по порядку 3. Проверьте консоль браузера на ошибки Автор: Сергей Антропов Сайт: https://devops.org.ru
200 lines
8.4 KiB
HTML
200 lines
8.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Тест LogBoard+ API</title>
|
|
<style>
|
|
body { font-family: Arial, sans-serif; margin: 20px; }
|
|
.test-section { margin: 20px 0; padding: 15px; border: 1px solid #ccc; border-radius: 5px; }
|
|
.success { color: green; }
|
|
.error { color: red; }
|
|
.info { color: blue; }
|
|
button { padding: 10px 20px; margin: 5px; }
|
|
pre { background: #f5f5f5; padding: 10px; border-radius: 3px; overflow-x: auto; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Тест LogBoard+ API</h1>
|
|
|
|
<div class="test-section">
|
|
<h3>1. Проверка токена в localStorage</h3>
|
|
<button onclick="checkToken()">Проверить токен</button>
|
|
<div id="tokenResult"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>2. Тест входа в систему</h3>
|
|
<button onclick="testLogin()">Войти (admin/admin)</button>
|
|
<div id="loginResult"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>3. Тест получения контейнеров</h3>
|
|
<button onclick="testContainers()">Получить контейнеры</button>
|
|
<div id="containersResult"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>4. Тест WebSocket</h3>
|
|
<button onclick="testWebSocket()">Тест WebSocket</button>
|
|
<div id="websocketResult"></div>
|
|
</div>
|
|
|
|
<div class="test-section">
|
|
<h3>5. Очистка</h3>
|
|
<button onclick="clearToken()">Очистить токен</button>
|
|
<div id="clearResult"></div>
|
|
</div>
|
|
|
|
<script>
|
|
const baseUrl = 'http://localhost:9001';
|
|
|
|
function log(elementId, message, type = 'info') {
|
|
const element = document.getElementById(elementId);
|
|
const className = type === 'success' ? 'success' : type === 'error' ? 'error' : 'info';
|
|
element.innerHTML = `<div class="${className}">${message}</div>`;
|
|
}
|
|
|
|
function checkToken() {
|
|
const token = localStorage.getItem('access_token');
|
|
if (token) {
|
|
log('tokenResult', `✅ Токен найден: ${token.substring(0, 50)}...`, 'success');
|
|
} else {
|
|
log('tokenResult', '❌ Токен не найден', 'error');
|
|
}
|
|
}
|
|
|
|
async function testLogin() {
|
|
try {
|
|
log('loginResult', '🔄 Выполняется вход...', 'info');
|
|
|
|
const response = await fetch(`${baseUrl}/api/auth/login`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
username: 'admin',
|
|
password: 'admin'
|
|
})
|
|
});
|
|
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
localStorage.setItem('access_token', data.access_token);
|
|
log('loginResult', `✅ Вход выполнен успешно! Токен сохранен.`, 'success');
|
|
} else {
|
|
const errorData = await response.json();
|
|
log('loginResult', `❌ Ошибка входа: ${errorData.detail || response.status}`, 'error');
|
|
}
|
|
} catch (error) {
|
|
log('loginResult', `❌ Ошибка: ${error.message}`, 'error');
|
|
}
|
|
}
|
|
|
|
async function testContainers() {
|
|
try {
|
|
const token = localStorage.getItem('access_token');
|
|
if (!token) {
|
|
log('containersResult', '❌ Токен не найден. Сначала выполните вход.', 'error');
|
|
return;
|
|
}
|
|
|
|
log('containersResult', '🔄 Получение контейнеров...', 'info');
|
|
|
|
const response = await fetch(`${baseUrl}/api/containers/services`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
});
|
|
|
|
if (response.ok) {
|
|
const containers = await response.json();
|
|
log('containersResult', `✅ Получено контейнеров: ${containers.length}`, 'success');
|
|
|
|
const containerList = containers.slice(0, 3).map(c =>
|
|
`${c.name} (${c.status})`
|
|
).join('<br>');
|
|
|
|
document.getElementById('containersResult').innerHTML +=
|
|
`<div class="success">Первые 3 контейнера:<br>${containerList}</div>`;
|
|
} else {
|
|
const errorText = await response.text();
|
|
log('containersResult', `❌ Ошибка: ${response.status} - ${errorText}`, 'error');
|
|
}
|
|
} catch (error) {
|
|
log('containersResult', `❌ Ошибка: ${error.message}`, 'error');
|
|
}
|
|
}
|
|
|
|
function testWebSocket() {
|
|
const token = localStorage.getItem('access_token');
|
|
if (!token) {
|
|
log('websocketResult', '❌ Токен не найден. Сначала выполните вход.', 'error');
|
|
return;
|
|
}
|
|
|
|
log('websocketResult', '🔄 Подключение к WebSocket...', 'info');
|
|
|
|
// Получаем первый контейнер для теста
|
|
fetch(`${baseUrl}/api/containers/services`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(containers => {
|
|
if (containers.length === 0) {
|
|
log('websocketResult', '❌ Нет контейнеров для тестирования', 'error');
|
|
return;
|
|
}
|
|
|
|
const container = containers[0];
|
|
const wsUrl = `ws://localhost:9001/api/websocket/logs/${container.id}?tail=5&token=${token}&service=${container.name}`;
|
|
|
|
log('websocketResult', `🔗 Подключение к: ${wsUrl.substring(0, 80)}...`, 'info');
|
|
|
|
const ws = new WebSocket(wsUrl);
|
|
|
|
ws.onopen = function() {
|
|
log('websocketResult', '✅ WebSocket соединение установлено!', 'success');
|
|
};
|
|
|
|
ws.onmessage = function(event) {
|
|
const message = event.data;
|
|
log('websocketResult', `📨 Получено сообщение: ${message.substring(0, 100)}...`, 'success');
|
|
|
|
// Закрываем соединение после получения первого сообщения
|
|
setTimeout(() => {
|
|
ws.close();
|
|
log('websocketResult', '🔌 WebSocket соединение закрыто', 'info');
|
|
}, 1000);
|
|
};
|
|
|
|
ws.onerror = function(error) {
|
|
log('websocketResult', `❌ WebSocket ошибка: ${error}`, 'error');
|
|
};
|
|
|
|
ws.onclose = function() {
|
|
log('websocketResult', '🔌 WebSocket соединение закрыто', 'info');
|
|
};
|
|
})
|
|
.catch(error => {
|
|
log('websocketResult', `❌ Ошибка получения контейнеров: ${error.message}`, 'error');
|
|
});
|
|
}
|
|
|
|
function clearToken() {
|
|
localStorage.removeItem('access_token');
|
|
log('clearResult', '✅ Токен очищен', 'success');
|
|
}
|
|
|
|
// Автоматическая проверка токена при загрузке
|
|
window.onload = function() {
|
|
checkToken();
|
|
};
|
|
</script>
|
|
</body>
|
|
</html>
|