Skip to content

Глава 4.2: Отправка GET запросов

Время изучения: 45 минут


1. GET: Запрос телеметрии с космического флота

GET-запрос — это основная команда для получения данных. В нашем ЦУПе это эквивалентно запросу: "Центр Управления Флотом, доложите обстановку!"

Мы будем использовать fetch для отправки двух типов GET-запросов к нашему FastAPI-серверу:

  1. Получение всей коллекции: "Покажите мне весь мой флот".
  2. Получение одного ресурса: "Дайте подробную информацию о корабле с 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.

pip install python-multipart

Шаг 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("/")
# ...
Теперь наш API-сервер готов принимать запросы от фронтенда. Перезапустите 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) — вы увидите сообщение об ошибке.


Квиз для закрепления

1. Политика CORS в браузере нужна для...

2. Чтобы разрешить фронтенду на `localhost:5500` обращаться к FastAPI, нужно...

3. Для получения данных о конкретном ресурсе с ID=5, URL запроса будет выглядеть как:

4. Ключевое слово `await` в JavaScript можно использовать только внутри функции, объявленной с...

5. `event.preventDefault()` в обработчике отправки формы нужен, чтобы...


🚀 Итог главы:

Вы успешно настроили канал связи между "Землей" и "космосом" и научились запрашивать телеметрию!

  • 🛡️ Вы решили проблему "межпланетных помех", настроив CORS на своем FastAPI-сервере.
  • 🛰️ Реализовали функцию для получения и отображения всего списка космических аппаратов.
  • 🔭 Создали интерфейс для запроса данных о конкретном аппарате по его ID.

ЦУП получает данные! В следующей главе мы перейдем к активным действиям: будем отправлять команды на создание, обновление и удаление наших космических кораблей.

📌 Проверка:

  • Убедитесь, что ваш FastAPI-сервер запущен с настроенным CORSMiddleware.
  • Проверьте, что при нажатии на кнопку "Запросить данные" на странице появляется список кораблей.
  • Убедитесь, что форма поиска по ID корректно находит существующие аппараты и сообщает об ошибке для несуществующих.

⚠️ Если ошибки:

  • CORS error в консоли браузера: Либо вы не перезапустили uvicorn после добавления CORSMiddleware, либо адрес вашего фронтенда (например, http://127.0.0.1:5500) не добавлен в список origins.
  • Failed to fetch: Проверьте, что ваш FastAPI-сервер запущен и доступен по адресу, указанному в API_BASE_URL.