Эндпоинты — это точки входа в ваше веб-приложение. Каждый эндпоинт соответствует определенному URL-адресу и методу HTTP (GET, POST, PUT, DELETE и т.д.). В FastAPI создание эндпоинтов чрезвычайно просто и интуитивно понятно благодаря использованию декораторов и аннотаций типов. В начале немного теории, а потом закрепим тему на практике.

HTTP методы

  • HTTP методы описывают действия, которые можно выполнить с ресурсами на сервере. Основные методы включают:
  • GET: Запрашивает данные с сервера. Обычно используется для получения информации.
  • POST: Отправляет данные на сервер. Используется для создания новых ресурсов.
  • PUT: Отправляет данные на сервер для обновления существующего ресурса.
  • DELETE: Удаляет ресурс на сервере.

Маршрутизация и параметры URL

Маршрутизация

Маршрутизация — это процесс определения, какой код будет выполнен при обращении к определенному URL-адресу. В FastAPI маршрутизация реализуется с помощью декораторов. Декораторы — это специальные функции, которые изменяют поведение других функций.

Пример:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "FastAPI"}

В этом примере декоратор @app.get(«/») указывает, что функция read_root будет вызываться, когда пользователь обращается к корневому URL / с методом GET.

Параметры URL

Параметры URL позволяют передавать данные в эндпоинты через сам URL. Например, если у нас есть URL /items/{item_id}, то {item_id} является параметром URL.

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def read_item(item_id: int):
    return {"item_id": item_id}

В этом примере item_id — это параметр URL, который будет передан в функцию read_item. Тип параметра указан как int, что позволяет FastAPI автоматически проверять и конвертировать значение в целое число.

Параметры запросов

Параметры запросов передаются через строку запроса после символа ? в URL. Они позволяют передавать дополнительные данные в эндпоинт без необходимости включать их в сам URL.

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

В этом примере параметры skip и limit передаются через строку запроса, например: /items/?skip=5&limit=20.

Запросы и их параметры

Запросы

FastAPI позволяет легко обрабатывать различные типы запросов, передаваемых клиентом. Запросы могут содержать параметры URL, параметры строки запроса, тела запросов и заголовки.

  • Параметры URL: передаются как часть пути URL.
  • Параметры строки запроса: передаются после символа ? в URL.
  • Тело запроса: передается в HTTP запросах, обычно в методах POST и PUT, и содержит данные в формате JSON, XML или другого типа.
  • Заголовки: содержат метаинформацию о запросе и передаются в HTTP заголовках.

FastAPI автоматически разбирает и валидирует параметры запросов, предоставляя разработчику удобный интерфейс для работы с ними. Рассмотрим несколько примеров.

Параметры пути

Параметры пути включаются в URL и определяются в функции эндпоинта:

@app.get("/users/{user_id}")
async def read_user(user_id: int):
    return {"user_id": user_id}

В этом примере user_id будет извлечен из URL и передан в функцию read_user.

Параметры строки запроса

Параметры строки запроса указываются в функции эндпоинта как параметры функции с указанием значений по умолчанию:

@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return {"skip": skip, "limit": limit}

Тело запроса

Для получения данных из тела запроса используется специальная функция Body:

from fastapi import Body

@app.post("/items/")
async def create_item(item: dict = Body(...)):
    return item

Этот пример показывает, как получить данные из тела запроса и вернуть их обратно в ответе.

Заголовки

Для работы с заголовками запроса используется функция Header:

from fastapi import Header

@app.get("/items/")
async def read_items(user_agent: str = Header(None)):
    return {"User-Agent": user_agent}

В этом примере user_agent будет извлечен из заголовков HTTP запроса и передан в функцию.

Практика

В этой практике мы создадим несколько примеров эндпоинтов в FastAPI, работающих с параметрами URL и параметрами запросов. Мы рассмотрим, как обрабатывать различные типы параметров и как использовать их для создания гибких и мощных API.

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

Прежде чем начать, убедитесь, что у вас установлен FastAPI и Uvicorn. Если нет, следуйте инструкциям из первой статьи.

Создайте новый файл проекта main.py и начнем с базовой настройки приложения.

from fastapi import FastAPI

app = FastAPI()

Пример 1: Обработка параметров пути

В этом примере мы рассмотрим, как создать эндпоинт для получения информации о пользователе по его ID. Мы будем использовать параметр пути для передачи ID пользователя. Давайте рассмотрим пример, где у нас есть три пользователя с различными именами и ролями, и мы будем получать информацию о пользователе по его ID.

Для начала создадим словарь, содержащий информацию о пользователях:

from fastapi import FastAPI, HTTPException

# Создаем экземпляр FastAPI
app = FastAPI()

# Данные о пользователях
users = [
    {"id": 1, "name": "Alice", "role": "admin"},
    {"id": 2, "name": "Bob", "role": "user"},
    {"id": 3, "name": "Charlie", "role": "guest"}
]

# Эндпоинт для получения данных о пользователе по его ID
@app.get("/users/{user_id}")
async def read_user(user_id: int):
    # Ищем пользователя по ID
    for user in users:
        if user["id"] == user_id:
            return user
    # Если пользователь не найден, выбрасываем исключение
    raise HTTPException(status_code=404, detail="User not found")

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

uvicorn main:app --reload

Теперь, если вы перейдете по следующему адресу http://127.0.0.1:8000/users/1, то получите ответ:

{
    "id": 1,
    "name": "Alice",
    "role": "admin"
}

Пример 2: Параметры строки запроса

Давайте создадим пример, в котором у нас есть пять пользователей, и мы добавим эндпоинт для получения списка пользователей с возможностью пропустить определенное количество записей и задать лимит на количество возвращаемых записей. Эти параметры будут передаваться через строку запроса.

from fastapi import FastAPI
from typing import List

app = FastAPI()

# Данные о пользователях
users = [
    {"id": 1, "name": "Alice", "role": "admin"},
    {"id": 2, "name": "Bob", "role": "user"},
    {"id": 3, "name": "Charlie", "role": "guest"},
    {"id": 4, "name": "David", "role": "moderator"},
    {"id": 5, "name": "Eve", "role": "user"}
]

# Эндпоинт для получения списка пользователей с параметрами строки запроса
@app.get("/users/")
async def read_users(skip: int = 0, limit: int = 10) -> List[dict]:
    return users[skip: skip + limit]

Если вы перейдете по адресу http://127.0.0.1:8000/users/?skip=1&limit=3, вы увидите следующий ответ:

[
    {"id": 2, "name": "Bob", "role": "user"},
    {"id": 3, "name": "Charlie", "role": "guest"},
    {"id": 4, "name": "David", "role": "moderator"}
]

Пример 3: Параметры запроса с опциональными значениями

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

from fastapi import FastAPI
from typing import Optional, List

app = FastAPI()

# Данные о пользователях
users = [
    {"id": 1, "name": "Alice", "role": "admin"},
    {"id": 2, "name": "Bob", "role": "user"},
    {"id": 3, "name": "Charlie", "role": "guest"},
    {"id": 4, "name": "David", "role": "moderator"},
    {"id": 5, "name": "Eve", "role": "user"}
]

# Эндпоинт для получения списка пользователей с опциональным параметром поиска по имени
@app.get("/users/")
async def read_users(skip: int = 0, limit: int = 10, search: Optional[str] = None) -> List[dict]:
    filtered_users = users
    # Если передан параметр поиска, фильтруем пользователей по имени
    if search:
        filtered_users = [user for user in users if search.lower() in user["name"].lower()]
    # Возвращаем пользователей с учетом параметров skip и limit
    return filtered_users[skip: skip + limit]

Здесь создаем эндпоинт /users/, который принимает параметры строки запроса skip, limit и опциональный параметр search. Если параметр search передан, мы фильтруем список пользователей по имени, игнорируя регистр. Затем возвращаем срез списка пользователей в зависимости от значений skip и limit.

Если вы перейдете по адресу http://127.0.0.1:8000/users/?skip=1&limit=3&search=bo, вы увидите следующий ответ:

[
    {"id": 2, "name": "Bob", "role": "user"}
]

Таким образом, мы создали эндпоинт для получения списка пользователей с возможностью пропускать определенное количество записей, задавать лимит на количество возвращаемых записей и искать пользователей по имени с использованием FastAPI.