JavaRush /Курсы /Модуль 4: FastAPI /Полная реализация API с интеграцией внешнего сервиса

Полная реализация API с интеграцией внешнего сервиса

Модуль 4: FastAPI
16 уровень , 9 лекция
Открыта

В этой лекции мы соберем все ранее изученные концепции и реализуем полноценный API на FastAPI с интеграцией внешнего сервиса. Мы организуем проект, создадим эндпоинты, подключимся к внешнему API, обработаем полученные данные и добавим валидацию, а также напишем простые тесты. Чтобы сделать проект интересным, мы будем работать с OpenWeatherMap API для предоставления данных о погоде.

Мы реализуем небольшой API-приложение, которое позволяет клиентам:

  1. Запрашивать текущую информацию о погоде по городу.
  2. Валидация данных (например, проверим, что город действительно указан).
  3. Обрабатывать ошибки в случае проблем с внешним API (например, неверный API-ключ или ошибки сети).

Такие знания пригодятся при создании реальных проектов, где требуется взаимодействие с другими сервисами: интеграция с платежными системами, соцсетями, аналитическими инструментами и т.д. Этот навык также часто проверяется на собеседованиях.


Создание структуры проекта

Сначала организуем каталог проекта. Самая базовая структура будет выглядеть так:


weather_app/
├── app/
│   ├── main.py
│   ├── api/
│   │   ├── __init__.py
│   │   ├── weather.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── schemas.py
│   ├── services/
│       ├── __init__.py
│       ├── weather_service.py
│   ├── settings.py
├── requirements.txt
  • app/main.py — основной файл для запуска приложения.
  • app/api/weather.py — здесь будем описывать маршруты.
  • app/models/schemas.py — храним Pydantic-схемы.
  • app/services/weather_service.py — реализуем логику интеграции с внешним API.
  • app/settings.py — настройки проекта, например API-ключи.

Установка зависимостей

Начнем с установки библиотек. Нам понадобится FastAPI, httpx и Pydantic:

pip install fastapi uvicorn httpx

Обновите requirements.txt:

fastapi
httpx
uvicorn

Настройка основного файла приложения

Создадим минимальный файл main.py:


from fastapi import FastAPI
from app.api.weather import router as weather_router

app = FastAPI(
    title="Weather API",
    description="A simple API to fetch weather information from OpenWeatherMap",
    version="1.0.0"
)

app.include_router(weather_router, prefix="/weather")

Здесь мы создаем экземпляр FastAPI и подключаем маршруты из модуля weather.


Реализация эндпоинта для получения погоды

Добавим файл app/api/weather.py:


from fastapi import APIRouter, HTTPException, Query
from app.models.schemas import WeatherResponse
from app.services.weather_service import get_weather_data

router = APIRouter()

@router.get("/", response_model=WeatherResponse)
async def get_weather(city: str = Query(..., description="City name to fetch weather data")):
    """
    Fetch weather data for a given city.
    """
    weather_data = await get_weather_data(city)
    if not weather_data:
        raise HTTPException(status_code=404, detail="Weather data not found")
    return weather_data
  1. Маршрут: Создаем маршрут GET /weather/, принимающий параметр city.
  2. Описание: Используем Query для описания параметра города.
  3. Ответ: Возвращаем JSON в виде, описанном в схеме WeatherResponse.

Описание Pydantic-схемы

Теперь создадим файл app/models/schemas.py, где опишем схему ответа:


from pydantic import BaseModel

class WeatherResponse(BaseModel):
    city: str
    temperature: float
    description: str

Этот класс задает структуру возвращаемых данных: город, температура и описание погоды.


Написание сервиса для работы с внешним API

Добавим файл app/services/weather_service.py:


import httpx
from app.settings import OPENWEATHERMAP_API_KEY

BASE_URL = "http://api.openweathermap.org/data/2.5/weather"

async def get_weather_data(city: str):
    """
    Fetch weather data from OpenWeatherMap API.
    """
    params = {
        "q": city,
        "appid": OPENWEATHERMAP_API_KEY,
        "units": "metric"  # Get temperature in Celsius
    }

    async with httpx.AsyncClient() as client:
        response = await client.get(BASE_URL, params=params)
        if response.status_code != 200:
            return None
        data = response.json()
        return {
            "city": data["name"],
            "temperature": data["main"]["temp"],
            "description": data["weather"][0]["description"]
        }
  1. Функция отправляет асинхронный GET-запрос к OpenWeatherMap API.
  2. Парсит ответ и извлекает нужные данные: имя города, температуру и описание.

Настройка API-ключа

Создадим файл app/settings.py:


import os

OPENWEATHERMAP_API_KEY = os.getenv("OPENWEATHERMAP_API_KEY", "your_api_key_here")

Не забудьте заменить your_api_key_here на ваш реальный API-ключ. Или установите переменную окружения OPENWEATHERMAP_API_KEY.


Обработка ошибок

Если у сервиса OpenWeatherMap возникнет ошибка (например, неверный API-ключ или несуществующий город), мы возвращаем None. В маршруте это преобразуется в HTTP-ошибку 404 через HTTPException.

Можно улучшить обработку ошибок:


        if response.status_code == 404:
            return {"error": "City not found"}
        elif response.status_code == 401:
            return {"error": "Invalid API key"}
        response.raise_for_status()

Тестирование эндпоинта

Простой клиент для проверки:
создайте файл test_weather.py:


import pytest
from fastapi.testclient import TestClient
from app.main import app

client = TestClient(app)

@pytest.mark.parametrize("city", ["London", "Paris", "Tokyo"])
def test_get_weather(city):
    response = client.get(f"/weather/?city={city}")
    assert response.status_code == 200
    assert "temperature" in response.json()
  1. Тесты проверяют несколько городов.
  2. Убедитесь, что ответ содержит поле temperature.

Запуск приложения

Запустите сервер с помощью команды:

uvicorn app.main:app --reload

Перейдите на http://127.0.0.1:8000/docs, чтобы протестировать эндпоинт через Swagger UI.

1
Задача
Модуль 4: FastAPI, 16 уровень, 9 лекция
Недоступна
Создание простого API для интеграции с внешним сервисом
Создание простого API для интеграции с внешним сервисом
1
Задача
Модуль 4: FastAPI, 16 уровень, 9 лекция
Недоступна
Интеграция с внешним API
Интеграция с внешним API
3
Опрос
Обработка ошибок при работе с внешними сервисами, 16 уровень, 9 лекция
Недоступен
Обработка ошибок при работе с внешними сервисами
Обработка ошибок при работе с внешними сервисами
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ