Какие возможности кастомизации предоставляет FastAPI?

Ответ

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

Основные примеры кастомизации:

  1. Кастомные валидаторы Pydantic: Используются для обеспечения целостности данных и применения бизнес-правил, которые не могут быть выражены стандартными типами Pydantic. Это позволяет гибко контролировать входящие данные.

    from pydantic import BaseModel, validator
    
    class User(BaseModel):
        name: str
    
        @validator('name')
        def name_must_contain_space(cls, v):
            if ' ' not in v:
                raise ValueError('Name must contain a space')
            return v.title()
  2. Кастомные Middleware: Позволяют перехватывать запросы и ответы на глобальном уровне, реализуя сквозную функциональность, такую как логирование, аутентификация, добавление заголовков или обработка CORS. Это централизует общую логику.

    from fastapi import FastAPI, Request
    from starlette.responses import Response
    
    app = FastAPI()
    
    @app.middleware("http")
    async def add_process_time_header(request: Request, call_next):
        # Логика до обработки запроса
        response = await call_next(request)
        # Логика после обработки запроса
        response.headers["X-Custom-Header"] = "Custom Value"
        return response
  3. Кастомные обработчики ошибок: Используются для предоставления единообразных и информативных ответов при возникновении исключений, улучшая пользовательский опыт и упрощая отладку для клиентов API. Это обеспечивает предсказуемое поведение при ошибках.

    from fastapi import FastAPI, HTTPException, Request
    from fastapi.responses import JSONResponse
    
    app = FastAPI()
    
    @app.exception_handler(ValueError)
    async def value_error_handler(request: Request, exc: ValueError):
        return JSONResponse(
            status_code=400,
            content={"message": f"Некорректные данные: {exc}"}
        )
    
    @app.get("/test-error/{value}")
    async def test_error(value: str):
        if value == "invalid":
            raise ValueError("Значение не может быть 'invalid'")
        return {"message": "OK"}

Помимо этого, FastAPI позволяет кастомизировать OpenAPI-документацию, систему внедрения зависимостей (Dependency Injection), маршрутизацию и многое другое, что делает его очень гибким и расширяемым фреймворком.

Ответ 18+ 🔞

Слушай, ну это ж просто пиздец какой-то, как же FastAPI-то всё можно по-своему настроить! Прямо как конструктор, блядь, для взрослых дядек, которые пишут API. Хочешь — валидацию свою прикрутишь, хочешь — запросы на лету перехватывай, а хочешь — ошибки так красиво заверни, что клиент аж прослезится, сука.

Вот на что, блядь, можно руки наложить, если совсем охуел от стандартных возможностей:

  1. Свои валидаторы в Pydantic, ёпта. Ну стандартные типы — это, конечно, хорошо, но жизнь-то, блядь, сложнее! Вот, например, имя пользователя должно содержать пробел. Ну и как это стандартным str проверить, а? Правильно, нихуя. Пишем свой валидатор и наслаждаемся.

    from pydantic import BaseModel, validator
    
    class User(BaseModel):
        name: str
    
        @validator('name')
        def name_must_contain_space(cls, v):
            if ' ' not in v:
                raise ValueError('Name must contain a space')
            return v.title()

    Смотри, какая хитрая жопа: если пробела нет — выёбывается с ошибкой. А если есть — ещё и первую букву каждого слова в заглавную сделает. Красота, блядь!

  2. Своё промежуточное ПО, оно же Middleware. Это такая, блядь, штука, которая встаёт между клиентом и твоим кодом, как охранник в клубе. Все запросы и ответы через неё проходят. Хочешь логировать? Пожалуйста. Хочешь ко всем ответам прилепить свою хитрожопую заголовуху? Да не вопрос!

    from fastapi import FastAPI, Request
    from starlette.responses import Response
    
    app = FastAPI()
    
    @app.middleware("http")
    async def add_process_time_header(request: Request, call_next):
        # Тут можешь, блядь, что-то сделать ДО того, как запрос попадёт в твой ендпоинт
        response = await call_next(request)
        # А тут — ПОСЛЕ, когда ответ уже готов, но ещё не ушёл
        response.headers["X-Custom-Header"] = "Custom Value"
        return response

    Вот и весь секрет, сука. Всё, что глобально и для всех ручек — сюда.

  3. Свои обработчики косяков. Ну а что, стандартные HTTPException — это, конечно, классика, но скучно, блядь! А если у тебя своя, ебаная бизнес-логика и свои исключения? Клиенту же прилетит какая-то хуйня непонятная, а он потом тебе в поддержку: «чё за ошибка, я ничего не делал!». А ты ему — красивый, внятный JSON, где всё по полочкам разложено.

    from fastapi import FastAPI, HTTPException, Request
    from fastapi.responses import JSONResponse
    
    app = FastAPI()
    
    @app.exception_handler(ValueError)
    async def value_error_handler(request: Request, exc: ValueError):
        return JSONResponse(
            status_code=400,
            content={"message": f"Некорректные данные: {exc}"}
        )
    
    @app.get("/test-error/{value}")
    async def test_error(value: str):
        if value == "invalid":
            raise ValueError("Значение не может быть 'invalid'")
        return {"message": "OK"}

    Видишь? Поймали ValueError — завернули в красивый ответ с кодом 400. Клиент доволен, ты спокоен. Идиллия, блядь.

А ещё, ёпта, можно документацию OpenAPI свою нарисовать, зависимости кастомные придумать, маршрутизацию извратить — да хуй его знает, что ещё! В общем, инструмент на все случаи жизни, главное — не перестараться, а то получится не фреймворк, а ёбаный Франкенштейн.