← Назад к вопросам

Когда информация проходит валидацию?

2.0 Middle🔥 191 комментариев
#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Границы валидации данных

Валидация информации может происходить на разных этапах жизненного цикла приложения, и выбор момента валидации критичен для надёжности и производительности системы.

На уровне приложения (на клиенте)

Обычно это первая линия защиты. Фронтенд валидирует введённые данные перед отправкой на сервер, чтобы дать пользователю немедленный фидбэк:

# На клиенте (JavaScript/React), но логика аналогична
# Быстрая синхронная валидация
if email and not is_valid_email(email):
    show_error("Некорректный формат email")
    return  # Не отправляем на сервер

Плюсы: UX улучшается, экономим трафик и запросы к серверу.

На уровне API (граница приложения)

Это вторая и обязательная линия защиты. Каждый запрос должен валидироваться на сервере, даже если фронтенд уже проверил данные. Причины:

  • Клиент может быть скомпрометирован или отключен
  • Запросы могут приходить не только из вашего фронтенда (API, мобильное приложение, другие системы)
  • Необходимо гарантировать целостность данных
from fastapi import FastAPI, HTTPException, Body
from pydantic import BaseModel, EmailStr, Field

app = FastAPI()

class UserInput(BaseModel):
    email: EmailStr  # Автоматическая валидация формата
    age: int = Field(..., ge=0, le=150)  # Возраст от 0 до 150
    name: str = Field(..., min_length=1, max_length=100)

@app.post("/users")
async def create_user(user: UserInput):
    # Pydantic уже провалидировал данные здесь
    # Если данные невалидные, вернётся 422 Unprocessable Entity
    return {"status": "created", "user": user}

На уровне бизнес-логики (domain layer)

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

# domain/services/user_service.py
from domain.exceptions import ValidationError

class UserService:
    def create_user(self, email: str, age: int) -> User:
        # Синтаксис уже проверен на граница API
        # Проверяем бизнес-правила
        
        if self.user_repository.exists(email):
            raise ValidationError("Пользователь с такой почтой уже существует")
        
        if age < 18:
            raise ValidationError("Пользователи должны быть старше 18 лет")
        
        user = User(email=email, age=age)
        self.user_repository.save(user)
        return user

На уровне базы данных (последняя линия защиты)

Уровень БД защищает целостность данных от багов приложения:

CREATE TABLE users (
    id UUID PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    age INT CHECK (age >= 0 AND age <= 150),
    created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);

Важно: Ограничения БД не должны заменять валидацию в приложении, а дополнять её.

Когда валидация происходит в коде?

# Полный цикл валидации

# 1. Граница API — структурная валидация (Pydantic)
@app.post("/register")
async def register(user: UserRegisterSchema):
    # user.email, user.password уже валидированы Pydantic
    
    # 2. Бизнес-логика — семантическая валидация
    try:
        created_user = await user_service.register(user.email, user.password)
    except ValidationError as e:
        raise HTTPException(status_code=400, detail=str(e))
    
    # 3. Если тут код, значит всё прошло валидацию
    return {"status": "success", "user_id": created_user.id}

Иерархия валидации (от быстрой к медленной)

  1. Тип данных — быстро (int, str, bool) → Pydantic
  2. Формат — быстро (email, UUID, URL) → Regex или библиотеки
  3. Диапазон/длина — быстро (min/max, length) → Pydantic
  4. Уникальность/существование — медленно (запрос к БД) → Domain layer
  5. Бизнес-правила — зависит (сложная логика) → Domain layer

Лучшие практики

✅ Валидируй везде:

  • На клиенте → быстрая обратная связь
  • На сервере → безопасность
  • В БД → целостность

✅ Структурную валидацию делай на границе:

from pydantic import BaseModel

class RequestSchema(BaseModel):
    # Все проверки сюда
    pass

✅ Бизнес-валидацию делай в domain layer:

class UserService:
    def register(self, email: str, password: str):
        # Здесь проверяем бизнес-правила
        pass

❌ Не полагайся только на фронтенд

❌ Не валидируй в обработчике (handler), делай в сервисе

В итоге: информация проходит валидацию непрерывно, на каждом уровне архитектуры, начиная с фронтенда и заканчивая БД. Каждый уровень отвечает за свой вид проверок.

Когда информация проходит валидацию? | PrepBro