Когда ваш API растёт, ошибки — неизбежная часть жизни. И нет ничего хуже, чем получать стандартное «Internal Server Error» без намёка на причину. FastAPI предлагает мощные инструменты для обработки ошибок и создания информативных, пользовательских ответов. Сегодня разберём, как сделать ваше приложение более дружелюбным к разработчикам и пользователям.
Почему важна правильная обработка ошибок?
Представьте ситуацию: вы вызываете метод API, и вместо ожидаемого ответа получаете:
{"detail": "Internal Server Error"}
Это примерно как получить пустую чашку вместо кофе в кафе. Вы не знаете, что пошло не так и почему. Хорошая обработка ошибок даёт:
- Понятные сообщения для разработчиков (чтобы легче было отладить).
- Дружественные ответы для клиентов API (чтобы не отпугнуть пользователей).
- Безопасность, скрывая внутренние детали системы.
Стандартные ошибки FastAPI
FastAPI из коробки предоставляет несколько стандартных HTTP-исключений:
- HTTPException — основа для создания пользовательских ошибок.
- RequestValidationError — ошибки валидации данных (обработку можно кастомизировать).
Пример обработки HTTPException
Создадим маршрут, который вызывает ошибку, если товар не найден:
from fastapi import FastAPI, HTTPException
app = FastAPI()
fake_products = {"1": "Ноутбук", "2": "Смартфон"}
@app.get("/products/{product_id}")
def read_product(product_id: str):
if product_id not in fake_products:
raise HTTPException(status_code=404, detail="Товар не найден")
return {"product": fake_products[product_id]}
Если перейти на http://127.0.0.1:8000/products/3, FastAPI вернёт:
{
"detail": "Товар не найден"
}
Что происходит:
- При отсутствии товара вызывается HTTPException.
- FastAPI автоматически формирует ответ с нужным статусом и сообщением.
Кастомизация обработки ошибок
Допустим, мы хотим перехватить все 404 ошибки и вернуть более дружелюбный ответ. Для этого создадим обработчик исключений.
from fastapi.responses import JSONResponse
from fastapi.requests import Request
@app.exception_handler(HTTPException)
async def custom_http_exception_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content={"message": f"Упс! Ошибка: {exc.detail}"}
)
Теперь 404 ошибки будут возвращать:
{"message": "Упс! Ошибка: Товар не найден"}
Обработка ошибок валидации данных
Если в запросе что-то не так (например, невалидные данные), FastAPI вызывает исключение RequestValidationError. Давайте обработаем его.
from fastapi.exception_handlers import request_validation_exception_handler
from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={"errors": exc.errors(), "message": "Ошибка валидации данных"}
)
Теперь при передаче неверных данных в запросе, клиент получит подробное описание ошибки.
Возвращение кастомных ответов
FastAPI позволяет не ограничиваться JSON-ответами. Вы можете возвращать HTML, файлы или даже кастомные объекты. Рассмотрим несколько примеров.
Возвращение HTML
Иногда нужно вернуть HTML-страницу вместо JSON (например, для простой ошибки 404):
from fastapi.responses import HTMLResponse
@app.get("/html", response_class=HTMLResponse)
async def read_html():
return """
<html>
<body>
<h1>Привет, FastAPI!</h1>
</body>
</html>
"""
FastAPI автоматически определит тип ответа как text/html.
Файловые ответы
Что если нужно отдать файл клиенту? FastAPI справится и с этим!
from fastapi.responses import FileResponse
@app.get("/download")
async def download_file():
return FileResponse("example.pdf", media_type='application/pdf', filename="download.pdf")
Теперь по маршруту /download пользователь скачает файл example.pdf.
Ответ с кастомным статусом и заголовками
Можно управлять статусом и заголовками ответа:
from fastapi.responses import JSONResponse
@app.get("/custom-response")
async def custom_response():
return JSONResponse(
status_code=201,
content={"message": "Ресурс успешно создан"},
headers={"X-Custom-Header": "MyValue"}
)
Заключение
Правильная обработка ошибок и кастомные ответы — основа качественного API. Сегодня мы научились ловить исключения, кастомизировать обработку ошибок и возвращать различные типы ответов. В следующей статье разберёмся с базами данных и посмотрим, как подключить их к FastAPI.