mock_sobes
← FastAPI + Pydantic v2 (валидация, OpenAPI)
middle correct_vs_wrong #347
Два способа возвращать ошибки из FastAPI-эндпоинта. Какой правильный?
Вариант 1
@app.post("/orders")
async def create_order(body: CreateOrderIn):
    try:
        order = await order_service.create(body)
    except StockEmptyError as e:
        return {"error": str(e), "code": "STOCK_EMPTY"}, 409  # ❌ tuple — это не valid FastAPI return
    except Exception as e:
        return {"error": "internal"}, 500
    return order
Вариант 2
from fastapi import HTTPException, status

class StockEmptyError(Exception):
    pass

# Один централизованный handler
@app.exception_handler(StockEmptyError)
async def stock_empty_handler(request: Request, exc: StockEmptyError):
    return JSONResponse(
        status_code=status.HTTP_409_CONFLICT,
        content={"detail": str(exc), "code": "STOCK_EMPTY"},
    )

@app.post(
    "/orders",
    response_model=OrderOut,
    status_code=201,
    responses={409: {"description": "Stock empty"}},
)
async def create_order(body: CreateOrderIn):
    # Бросаем — пусть handler разрулит. Эндпоинт чистый.
    order = await order_service.create(body)
    return order
    # При генерации OpenAPI — будет 409 в схеме, фронт это увидит.
Чтобы решить вопрос и сохранить попытку — войди.