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

Валідація вхідних даних у запитах

Модуль 4: FastAPI
Рівень 3 , Лекція 2
Відкрита

Уявіть, що ваш сервер — це нічний клуб, а вхідні дані — це люди, які намагаються потрапити на тусовку. Якщо ви не перевіряєте, хто заходить (вік, наявність квитка тощо), скоро почнеться хаос. У випадку з API хаос — це помилки, вразливості й поломка системи. Валідація вхідних даних дозволяє впевнитися, що сервер отримує саме ті дані, яких він очікує. Вона захищає від випадкового введення неправильних даних користувачем і навіть від навмисних спроб злому.

У FastAPI Pydantic моделі дають нам змогу легко автоматизувати цю перевірку і зробити її не тільки безпечною, а й зручною.


Використання Pydantic моделей для валідації запитів

Давайте почнемо з простого прикладу: ми хочемо створити endpoint, який приймає дані користувача (ім'я, вік і 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. В endpoint ми приймаємо 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

Уявімо, що користувач хоче знайти книгу по її автору. Зробимо endpoint, який приймає параметр 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.
  • Порядок аргументів в endpoint (Path, Query, Body) має значення. FastAPI використовує їх для розділення даних.
  • Не забувайте про вбудовані типи Pydantic, такі як EmailStr, IPv4Address, PositiveInt — вони полегшують життя.

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

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ