Глава 4.2: Отправка GET запросов
Время изучения: 45 минут
1. GET: Запрос телеметрии с космического флота
GET-запрос — это основная команда для получения данных. В нашем ЦУПе это эквивалентно запросу: "Центр Управления Флотом, доложите обстановку!"
Мы будем использовать fetch
для отправки двух типов GET-запросов к нашему FastAPI-серверу:
- Получение всей коллекции: "Покажите мне весь мой флот".
- Получение одного ресурса: "Дайте подробную информацию о корабле с ID 2".
💡 Космическая аналогия:
GET /spaceships
— это широковещательный запрос ко всему флоту с просьбой сообщить свои позывные.
GET /spaceships/3
— это адресный запрос к конкретному кораблю (МКС) с просьбой передать полные данные о его системах.
2. Проблема CORS: "Межпланетные помехи"
Прежде чем мы отправим запрос, нужно решить одну важную проблему. По умолчанию, браузеры из соображений безопасности запрещают веб-странице (нашему ЦУПу), загруженной с одного "домена" (file:///...
или http://localhost:5500
), делать запросы к API на другом "домене" (http://127.0.0.1:8000
).
Эта политика называется CORS (Cross-Origin Resource Sharing).
Чтобы разрешить нашему фронтенду общаться с бэкендом, нужно настроить FastAPI-сервер так, чтобы он говорил браузеру: "Все в порядке, я доверяю запросам с этого адреса".
Шаг 1: Устанавливаем python-multipart
Это необходимо для корректной работы middleware.
Шаг 2: Настраиваем CORS в main.py
Откройте ваш файл main.py
из проекта FastAPI и добавьте следующий код:
# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware # <-- Импортируем middleware
# ... ваш остальной код (модели, db_spaceships) ...
app = FastAPI(
title="Fleet Management API",
# ...
)
# --- НАСТРОЙКА CORS ---
# Указываем, какие "домены" (origins) могут отправлять запросы
origins = [
"http://localhost",
"http://localhost:8080",
"http://127.0.0.1:5500", # Адрес для Live Server в VS Code
"null" # Для запросов из локальных файлов file:///
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins, # Разрешаем указанные origins
allow_credentials=True,
allow_methods=["*"], # Разрешаем все методы (GET, POST и т.д.)
allow_headers=["*"], # Разрешаем все заголовки
)
# --- ВАШИ ЭНДПОИНТЫ НИЖЕ ---
@app.get("/")
# ...
uvicorn
, чтобы изменения вступили в силу!
3. Получаем список всех кораблей
Создадим интерфейс для отображения нашего флота.
Шаг 1: Обновляем index.html
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>ЦУП - Управление Флотом</title>
<style>
body { font-family: sans-serif; }
.ship-list { list-style: none; padding: 0; }
.ship-list li { border: 1px solid #ccc; margin-bottom: 10px; padding: 15px; border-radius: 5px; }
</style>
</head>
<body>
<h1>Панель управления космическим флотом</h1>
<button id="load-fleet-btn">Запросить данные о флоте</button>
<h2>Список аппаратов:</h2>
<ul id="fleet-list" class="ship-list">
<li>Ожидание команды...</li>
</ul>
<script src="app.js"></script> <!-- Подключаем внешний скрипт -->
</body>
</html>
Шаг 2: Создаем app.js
Рядом с index.html
создайте файл app.js
. В него мы вынесем всю логику.
// app.js
const API_BASE_URL = 'http://127.0.0.1:8000'; // URL нашего FastAPI сервера
const loadFleetBtn = document.getElementById('load-fleet-btn');
const fleetList = document.getElementById('fleet-list');
// Функция для загрузки и отображения флота
async function fetchAndDisplayFleet() {
try {
fleetList.innerHTML = '<li>Загрузка телеметрии...</li>';
// Отправляем GET-запрос на /spaceships
const response = await fetch(`${API_BASE_URL}/spaceships`);
if (!response.ok) {
throw new Error(`Ошибка сети: ${response.status}`);
}
const ships = await response.json(); // Получаем массив кораблей
// Очищаем список и отображаем данные
fleetList.innerHTML = '';
if (ships.length === 0) {
fleetList.innerHTML = '<li>В реестре нет ни одного аппарата.</li>';
return;
}
ships.forEach(ship => {
const listItem = document.createElement('li');
listItem.innerHTML = `
<strong>${ship.name} (ID: ${ship.id})</strong><br>
Тип: ${ship.type}<br>
Год запуска: ${ship.launch_year}<br>
Статус: ${ship.status}
`;
fleetList.appendChild(listItem);
});
} catch (error) {
console.error('Не удалось загрузить данные о флоте:', error);
fleetList.innerHTML = `<li>Ошибка: ${error.message}</li>`;
}
}
// Вешаем обработчик на кнопку
loadFleetBtn.addEventListener('click', fetchAndDisplayFleet);
- async/await: Мы использовали новый, более удобный синтаксис для работы с промисами. Мы разберем его подробно в главе 4.5. Пока просто знайте, что
await
"ждет" выполнения промиса, не блокируя страницу. try...catch
: Отличный способ обрабатывать ошибки вasync
функциях.
Шаг 3: Тестируем
Откройте index.html
в браузере (лучше всего через расширение Live Server в VS Code, которое запустит его на http://127.0.0.1:5500
). Нажмите кнопку "Запросить данные о флоте". Список ваших кораблей из FastAPI должен появиться на странице!
4. Получаем данные одного корабля
Теперь добавим форму для запроса информации по конкретному ID.
Шаг 1: Добавляем форму в index.html
<!-- index.html, после списка -->
<hr>
<h2>Запрос по ID</h2>
<form id="ship-form">
<input type="number" id="ship-id-input" placeholder="Введите ID аппарата" required>
<button type="submit">Найти аппарат</button>
</form>
<div id="ship-details" class="ship-list"></div>
Шаг 2: Добавляем логику в app.js
// app.js, в конец файла
const shipForm = document.getElementById('ship-form');
const shipIdInput = document.getElementById('ship-id-input');
const shipDetails = document.getElementById('ship-details');
async function fetchShipById(event) {
event.preventDefault(); // Предотвращаем перезагрузку страницы
const shipId = shipIdInput.value;
if (!shipId) {
alert('Пожалуйста, введите ID.');
return;
}
try {
shipDetails.innerHTML = '<li>Поиск аппарата...</li>';
// Отправляем GET-запрос на /spaceships/{id}
const response = await fetch(`${API_BASE_URL}/spaceships/${shipId}`);
if (response.status === 404) {
throw new Error('Аппарат с таким ID не найден в реестре.');
}
if (!response.ok) {
throw new Error(`Ошибка сети: ${response.status}`);
}
const ship = await response.json();
shipDetails.innerHTML = `
<li>
<strong>${ship.name} (ID: ${ship.id})</strong><br>
Тип: ${ship.type}<br>
Год запуска: ${ship.launch_year}<br>
Статус: ${ship.status}
</li>
`;
} catch (error) {
console.error(`Ошибка при поиске аппарата ${shipId}:`, error);
shipDetails.innerHTML = `<li>Ошибка: ${error.message}</li>`;
}
}
shipForm.addEventListener('submit', fetchShipById);
- Мы добавили отдельную обработку статуса
404
, чтобы дать пользователю более понятное сообщение об ошибке.
Шаг 3: Тестируем Обновите страницу, введите ID существующего корабля (например, 1) и нажмите "Найти аппарат". Вы должны увидеть его данные. Попробуйте ввести несуществующий ID (например, 99) — вы увидите сообщение об ошибке.
Квиз для закрепления
🚀 Итог главы:
Вы успешно настроили канал связи между "Землей" и "космосом" и научились запрашивать телеметрию!
- 🛡️ Вы решили проблему "межпланетных помех", настроив CORS на своем FastAPI-сервере.
- 🛰️ Реализовали функцию для получения и отображения всего списка космических аппаратов.
- 🔭 Создали интерфейс для запроса данных о конкретном аппарате по его ID.
ЦУП получает данные! В следующей главе мы перейдем к активным действиям: будем отправлять команды на создание, обновление и удаление наших космических кораблей.
📌 Проверка:
- Убедитесь, что ваш FastAPI-сервер запущен с настроенным
CORSMiddleware
.- Проверьте, что при нажатии на кнопку "Запросить данные" на странице появляется список кораблей.
- Убедитесь, что форма поиска по ID корректно находит существующие аппараты и сообщает об ошибке для несуществующих.
⚠️ Если ошибки:
- CORS error в консоли браузера: Либо вы не перезапустили
uvicorn
после добавленияCORSMiddleware
, либо адрес вашего фронтенда (например,http://127.0.0.1:5500
) не добавлен в списокorigins
.- Failed to fetch: Проверьте, что ваш FastAPI-сервер запущен и доступен по адресу, указанному в
API_BASE_URL
.