У цій лекції ми зануримось у стандартні HTTP-помилки, які є невід'ємною частиною роботи веб-застосунків, і розберемо їхню обробку у FastAPI. Розглянемо такі статус-коди, як 404 (Not Found) і 500 (Internal Server Error), їх природу, а також дізнаємося, як з ними працювати так, щоб не перетворювати життя користувачів і розробників на IT-антиутопію.
HTTP-помилки — це спосіб сервера повідомити клієнта (браузер або інший додаток), що щось пішло не так. Сервер повертає HTTP-статус-код, який представляє собою трицифрове число, що передає суть події. Ось невеличка "група підтримки" найпопулярніших категорій кодів помилок:
- 1xx: Інформаційні (наприклад, 102 — Processing). Ці трапляються рідко і нас не дуже цікавлять.
- 2xx: Все OK (наприклад, 200 — ОК). Так добре, що про це навіть говорити не треба.
- 3xx: Перенаправлення (наприклад, 301 — Moved Permanently). Ці нас теж не сильно хвилюють.
- 4xx: Клієнтські помилки. Типу 404 — Not Found — "Ти просиш знайти неіснуючого динозавра".
- 5xx: Серверні помилки. Наприклад, 500 — Internal Server Error — "Наш сервер впав, відправляємо програміста на лагодження".
Сьогодні ми зосередимось на двох найпоширеніших: 404 та 500.
404 — Not Found: "Цього тут немає, спробуй інші двері"
Помилка 404 сигналізує, що клієнт запросив якийсь ресурс (наприклад, /user/42), але сервер не зміг його знайти. Це може бути викликано:
- Неправильним URL (наприклад,
/userr/42замість/user/42). - Відсутністю відповідного ендпоінта на сервері.
- Ресурсом, який був видалений або ніколи не існував.
Обробка помилки 404 у FastAPI
FastAPI автоматично повертає 404 у тих випадках, коли маршруту (ендпоінта) немає в застосунку. Однак, щоб покращити досвід користувача, ми можемо кастомізувати обробку цієї помилки.
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/user/{user_id}")
async def get_user(user_id: int):
if user_id != 1: # У нас є тільки користувач з id=1
raise HTTPException(status_code=404, detail="Користувача не знайдено")
return {"user_id": user_id, "name": "Іван Іванов"}
Користувацька сторінка для 404
FastAPI дозволяє налаштувати кастомний обробник для 404, щоб замість стандартної JSON-відповіді повертати щось більш "людяне":
from fastapi.responses import JSONResponse
@app.exception_handler(404)
async def custom_404_handler(request, exc):
return JSONResponse(
status_code=404,
content={"message": "Ой! Те, що ви шукали, не знайдено. Спробуйте інший запит."}
)
Тепер, якщо користувач випадково відправить запит на неіснуючий ресурс, йому прийде більш дружнє повідомлення.
500 — Internal Server Error: коли сервер "впав"
Помилка 500 означає, що щось пішло не так не на боці клієнта (як у випадку 404), а на боці сервера. Зазвичай вона виникає через:
- Необроблені виключення (наприклад, ділення на нуль або відсутність доступу до бази даних).
- Неправильну конфігурацію сервера.
- Баги в коді (а коли їх у нас не буває?).
Приклад необробленої помилки:
@app.get("/divide")
async def divide_by_zero():
return {"result": 1 / 0} # Ділення на нуль
Як тільки користувач спробує цей ендпоінт, сервер поверне 500 з великим стек-трейсом у консолі.
Обробка помилки 500 у FastAPI
Спочатку нам треба навчитися ловити такі помилки, щоб не залишати користувача в паніці. Просте рішення — глобальний обробник помилок:
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
@app.exception_handler(Exception)
async def global_exception_handler(request, exc):
return JSONResponse(
status_code=500,
content={"message": "Упс! Щось пішло не так на сервері. Ми вже це лагодимо!"}
)
Тепер, навіть якщо ми забудемо обробити конкретну помилку, глобальний обробник візьме це на себе і відправить користувачу зрозуміле повідомлення.
Порівняння обробки 404 і 500
| Аспект | Помилка 404 | Помилка 500 |
|---|---|---|
| Причина | Ресурс не знайдено | Внутрішня помилка сервера |
| Відповідь за замовчуванням | 404 JSON (Not Found) | 500 JSON (Internal Server Error) |
| Хто винен? | Зазвичай користувач (клієнт) | Зазвичай розробник (сервер) |
| Як фіксити | Налаштування маршрутів і перевірка даних | Логування, моніторинг і налагодження коду |
Повний приклад кастомізації обробки помилок
Давайте створимо API, яке обробляє і 404, і 500, надаючи кастомні повідомлення для обох помилок:
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
app = FastAPI()
# Ендпоінт з прикладом
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id > 10: # У нас тільки 10 предметів
raise HTTPException(status_code=404, detail="Item not found")
return {"item_id": item_id, "name": f"Item {item_id}"}
# Кастомний обробник 404
@app.exception_handler(404)
async def not_found_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=404,
content={"message": "Ресурс не знайдено. Перевірте URL."}
)
# Глобальний обробник 500
@app.exception_handler(Exception)
async def server_error_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={"message": "На сервері сталася помилка. Ми вже знаємо про це!"}
)
Практична користь і типові помилки
- Виявлення причин. Використання HTTP-кодів (4xx, 5xx) допомагає швидко діагностувати проблемні зони в застосунку.
- Уникайте витоків інформації. Ніколи не показуйте користувачу стек-трейс або внутрішні помилки застосунку, особливо при 500.
- Логування врятує світ. Усі помилки повинні бути зафіксовані за допомогою інструментів логування, щоб ви могли їх проаналізувати пізніше.
Тепер ваше API готове до правильної обробки помилок 404 і 500, і користувачі не перелякаються несподіваними відповідями сервера! Ми налаштували і дружні повідомлення для клієнтів, і засоби для полегшення відладки для розробників.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ