JavaRush /Курси /Модуль 4: FastAPI /Навіщо потрібна обробка помилок: основні принципи

Навіщо потрібна обробка помилок: основні принципи

Модуль 4: FastAPI
Рівень 20 , Лекція 0
Відкрита

Уяви собі веб-додаток без обробки помилок. Користувач вводить навмисно некоректний запит, а замість дружнього повідомлення про помилку бачить стек викликів Python. Звучить лячно, правда? Неправильна або, що ще гірше, забута обробка помилок може зробити твій додаток не тільки незручним для користувачів, але й небезпечним.

Помилка в коді — це як несподіваний гість: іноді її можна ігнорувати, іноді — треба терміново латати наслідки її візиту, а іноді — краще підготуватися заздалегідь, щоб вона не була зовсім несподіванкою. У випадку веб-розробки грамотно налаштована обробка помилок допомагає:

  1. Покращити досвід користувача. Ми не хочемо, щоб користувачі бачили некрасиве повідомлення "500 Internal Server Error", коли можна показати інформативне повідомлення типу "Запитуваний ресурс не знайдено".
  2. Забезпечити безпеку. Вивід необроблених помилок може містити деталі реалізації додатку, які можуть бути використані зловмисником.
  3. Спростити налагодження. Логування помилок і розумний підхід до обробки допомагають швидко знаходити і виправляти баги.

Приклади помилок

Помилки бувають різні:

  • Передбачувані помилки. Наприклад, користувач відправляє форму без заповнення обов'язкового поля, і наша логіка валідації коректно обробляє це.
  • Непередбачувані помилки. Наприклад, база даних "упала", або стороннє API перестало відповідати — такі проблеми ми не завжди можемо передбачити, але все одно можемо підготуватися, щоб мінімізувати шкоду.

Якщо твій додаток зовсім не обробляє помилки, то він працює як якийсь капітан Титаніка — намагається плисти далі, незважаючи на айсберг попереду.


Основні принципи обробки помилок

Давай виділимо кілька перевірених принципів, які застосовують при обробці помилок.

Повідомлення користувачу

Перше і головне правило: користувач має бути в курсі, що щось пішло не так. Якщо запит виконується повільно і раптом кидає помилку, користувачу важливо розуміти причину. Наприклад, при спробі замовити товар користувач побачить повідомлення на кшталт "На жаль, цей товар більше недоступний", а не загадкове "Помилка 500".

У FastAPI ми можемо використовувати вбудовані механізми повернення HTTP-статусів і повідомлень. Наприклад, повернемо 404 код, якщо запитуваний ресурс не знайдено.


from fastapi import FastAPI, HTTPException

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}

Коли користувач запитує ресурс, якого немає, він побачить JSON-відповідь:


{
  "detail": "Item not found"
}

Логування помилок

Логування — це наш вірний друг-розробник. Воно не лише допомагає швидко знаходити баги, а й фіксує "зломи", неочікувані сценарії роботи додатку і навіть може служити доказом під час розбору інцидентів. FastAPI дозволяє легко інтегрувати модулі логування, такі як logging.

Приклад логування помилки:


import logging

logger = logging.getLogger("my_logger")

@app.get("/log-error")
async def log_error_example():
    try:
        x = 1 / 0  # Це явно призведе до помилки
    except ZeroDivisionError as e:
        logger.error(f"Помилка: {e}")
        raise HTTPException(status_code=500, detail="Internal Server Error")

У логах ти побачиш, як помилка була зафіксована:


ERROR:my_logger: Помилка: division by zero

Панікувати не можна, логувати!

Коли додаток дає збій, дуже важливо не зробити ще гірше. Найчастіша помилка — це показувати користувачу занадто багато технічної інформації: відлагоджувальні повідомлення, стеки викликів і деталі "всередині". Це не тільки лякає звичайного користувача, але й може видати зайву інформацію зловмиснику.

Ось як робити не треба:


@app.get("/error")
async def bad_error():
    return 1 / 0  # Ой...

У такому вигляді помилка просто вилетить назовні без будь-якої спроби її зловити або пояснити. Краще вже просто сказати, що щось пішло не так — і не видавати всю "кухню".


Практичні сценарії обробки помилок

Іноді простого коду raise HTTPException недостатньо — треба подумати і про те, як помилка виглядатиме для користувача. Нижче — кілька життєвих ситуацій.

Повідомлення про помилку у вигляді сторінки

Іноді користувач очікує не JSON-відповідь, а повністю кастомізовану сторінку помилки. Наприклад, для помилки 404 ми можемо повернути HTML-сторінку.


from fastapi.responses import HTMLResponse

@app.get("/custom-404", response_class=HTMLResponse)
async def custom_not_found():
    raise HTTPException(
        status_code=404,
        detail="<h1>Упс! Сторінку не знайдено</h1><p>Схоже, ви зайшли не туди.</p>",
    )

Відвідувач побачить оптимістичне повідомлення, а не грубий текст помилки.

Повідомлення з деталями для розробників

Зазвичай розробники тестують API за допомогою інструментів типу Swagger або Postman. У таких випадках корисно, якщо система може видавати розширені дані для налагодження, але тільки за певних умов (наприклад, у режимі розробки):


DEBUG_MODE = True

@app.get("/debug-error")
async def debug_error():
    try:
        1 / 0
    except ZeroDivisionError as e:
        if DEBUG_MODE:
            raise HTTPException(status_code=500, detail=f"Помилка: {e}")
        else:
            raise HTTPException(status_code=500, detail="Internal Server Error")

У режимі DEBUG_MODE=True ми бачимо точну інформацію, але в продакшені такі деталі залишаться прихованими.


Висновок

Тепер ми розуміємо, як важливо приділяти увагу обробці помилок. У наступних лекціях розберемо більш складні теми: як обробляти стандартні HTTP-помилки (наприклад, 404 і 500), як створювати кастомні обробники, власні виключення, а також як логувати помилки і діагностувати їх за допомогою middleware. Запасайся терпінням — попереду глибоке занурення!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ