JavaRush /Курсы /Модуль 4: FastAPI /Валидация входных данных в запросах

Валидация входных данных в запросах

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

Представьте, что ваш сервер — это ночной клуб, а входные данные — это люди, пытающиеся пройти на вечеринку. Если вы не проверяете, кто заходит (возраст, наличие билета и т.д.), у вас скоро начнётся хаос. В случае API хаос — это ошибки, уязвимости и поломка системы. Валидация входных данных позволяет убедиться, что сервер получает именно те данные, которые он ожидает. Она защищает от случайного ввода неверных данных пользователем и даже от умышленных попыток взлома.

В FastAPI Pydantic модели позволяют нам с легкостью автоматизировать эту проверку и сделать её не только безопасной, но и удобной.


Использование Pydantic моделей для валидации запросов

Давайте начнем с простого примера: мы хотим создать эндпоинт, который принимает данные пользователя (имя, возраст и email) и возвращает их обратно, если они прошли проверку.

Пример


from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()

# Создаем Pydantic-модель для валидации данных
class User(BaseModel):
    name: str
    age: int
    email: EmailStr

@app.post("/users/")
async def create_user(user: User):
    # Если данные в user прошли валидацию — возвращаем их
    return user

Объяснение:

  1. Мы создали класс User, унаследованный от BaseModel. Эта модель определяет схему входных данных.
  2. Для поля email мы использовали специальный тип EmailStr из Pydantic, который автоматически проверяет, что переданная строка является корректным email-адресом.
  3. В эндпоинте мы принимаем user как аргумент функции — FastAPI автоматически проверяет, что переданные данные соответствуют модели User.

Теперь, если вы отправите запрос с некорректными данными:


curl -X POST "http://127.0.0.1:8000/users/" -H "Content-Type: application/json" -d '{"name": "Alice", "age": "not_a_number", "email": "not_an_email"}'

Вы получите ответ:


{
    "detail": [
        {
            "loc": ["body", "age"],
            "msg": "value is not a valid integer",
            "type": "type_error.integer"
        },
        {
            "loc": ["body", "email"],
            "msg": "value is not a valid email address",
            "type": "value_error.email"
        }
    ]
}

FastAPI сам заботится о проверке данных и возвращает подробные сообщения об ошибках.


Передача данных через тело запроса

Модели Pydantic идеально подходят для данных, передаваемых через тело запроса (Request Body). FastAPI автоматически ожидает JSON-структуру, соответствующую модели.

Пример: регистрация книги


from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

# Модель данных для книги
class Book(BaseModel):
    title: str
    author: str
    pages: int

@app.post("/books/")
async def add_book(book: Book):
    return {"message": f"Book '{book.title}' has been successfully added!"}

Попробуем отправить запрос:


curl -X POST "http://127.0.0.1:8000/books/" -H "Content-Type: application/json" -d '{"title": "1984", "author": "George Orwell", "pages": 328}'

Ответ:


{
    "message": "Book '1984' has been successfully added!"
}

Попробуйте отправить запрос с некорректными данными, например, пропустив поле title. FastAPI мгновенно уведомит вас об этом:


{
    "detail": [
        {
            "loc": ["body", "title"],
            "msg": "field required",
            "type": "value_error.missing"
        }
    ]
}

Использование Pydantic для обработки Query Parameters

Не только данные в теле запроса заслуживают валидации. Часто встречается необходимость проверять данные, переданные через параметры запроса (Query Parameters).

Пример с Query Parameters

Представим, что пользователь хочет найти книгу по её автору. Мы сделаем эндпоинт, который принимает параметр author и использует Pydantic для проверки.


from typing import Annotated
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/books/")
async def get_books(author: Annotated[str, Query(min_length=3, max_length=50)]):
    return {"message": f"Поиск книг автора: {author}"}

Преимущества использования Annotated:

  • Явное определение метаданных: Annotated позволяет четко разделять тип данных и связанные с ним метаданные, что улучшает читаемость и поддержку кода.
  • Безопасность типов: Использование Annotated помогает избежать потенциальных ошибок, связанных с неправильной обработкой значений по умолчанию.

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

Попробуем запрос:


curl -X GET "http://127.0.0.1:8000/books/?author=Orwell"

Успешный ответ:


{
    "message": "Searching books by author: Orwell"
}

Если длина параметра author будет меньше 3 символов, FastAPI вернет ошибку:


{
    "detail": [
        {
            "loc": ["query", "author"],
            "msg": "ensure this value has at least 3 characters",
            "type": "value_error.any_str.min_length",
            "ctx": {"limit_value": 3}
        }
    ]
}

Валидация Path Parameters

В FastAPI используются Path Parameters для передачи идентификаторов и других данных в URL. Pydantic позволяет также валидировать такие параметры.

Приведём пример. Разработаем получение книги по ID.


from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/books/{book_id}")
async def get_book(book_id: int = Path(..., ge=1)):
    return {"message": f"Book with ID {book_id}"}

Объяснение:

  1. Используя Path(...), мы задаём ограничения на параметр пути. В данном случае book_id должен быть целым числом больше или равным 1 (ge=1).
  2. Если переданный идентификатор не соответствует этим требованиям, FastAPI вернет сообщение об ошибке.

Попробуем запрос:


curl -X GET "http://127.0.0.1:8000/books/5"

Успешный ответ:


{
    "message": "Book with ID 5"
}

Если передать некорректный ID, например, -3, результат будет таким:


{
    "detail": [
        {
            "loc": ["path", "book_id"],
            "msg": "ensure this value is greater than or equal to 1",
            "type": "value_error.number.not_ge",
            "ctx": {"limit_value": 1}
        }
    ]
}

Типичные ошибки и особенности

Работая с валидацией в Query, Path и Request Body, важно помнить:

  • Если вы забыли указать поле как обязательное (...), FastAPI автоматически сделает его опциональным со значением None.
  • Порядок аргументов в эндпоинте (Path, Query, Body) имеет значение. FastAPI использует их для разделения данных.
  • Не забывайте про встроенные типы Pydantic, такие как EmailStr, IPv4Address, PositiveInt — они упрощают жизнь.

Теперь, когда вы знаете, как валидировать входные данные, вы уверенно можете сказать, что вы — опытный "вышибала", который не пропустит плохие данные на закрытую API-вечеринку.

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