Обработка ошибок
В прошлом шаге мы узнали, что такое коды состояния и как они полезны для информирования клиента о состоянии запроса. Запросы могут возвращать ошибочные ответы, и эти ответы могут быть некрасивыми или содержать недостаточную информацию о причине сбоя.
Ошибки запросов могут возникать из-за попыток доступа к несуществующим ресурсам, защищенным страницам без достаточных разрешений и даже из-за ошибок сервера. Ошибки в FastAPI обрабатываются путем создания исключения с использованием класса HTTPException.
Поскольку это исключение Python, то его не возвращают, а вызывают. Это также означает, что если вы находитесь внутри функции, которая вызывается внутри вашей функции операции пути, и вы поднимаете HTTPException внутри этой функции, то она не будет выполнять остальной код в функции операции пути, а сразу завершит запрос и отправит HTTP-ошибку клиенту.
Класс HTTPException принимает три аргумента:
status_code: Код состояния, который будет возвращен для этого сбояdetail: Сопроводительное сообщение для отправки клиентуheaders: Необязательный параметр для ответов, требующих заголовков
В нашем текущем приложении получение несуществующей записи возвращает код статуса ответа 500 вместо кода статуса ответа 404
Первым делом мы доработаем нашу функцию получения одной записи. Мы добавим возможность возврата сообщения, когда задача не может быть найдена и вызывать HTTPException. С его помощью мы сможем вернуть адекватный код ответа на ошибку.
from fastapi import HTTPException
@app.get(path="/message/{message_id}")
async def get_message(message_id: int) -> Message:
try:
return messages_db[message_id]
except IndexError:
raise HTTPException(status_code=404, detail="Message not found")
И теперь при попытке получить не существующую запись, мы будем получать ошибку с кодом ответа 404 и сообщением об ошибке.
Также по аналогии мы можем добавить обработку ошибок и для других методов нашего приложения:
@app.put("/message/{message_id}")
async def update_message(message_id: int, message: str = Body()) -> str:
try:
edit_message = messages_db[message_id]
edit_message.text = message
return f"Message updated!"
except IndexError:
raise HTTPException(status_code=404, detail="Message not found")
@app.delete("/message/{message_id}")
async def delete_message(message_id: int) -> str:
try:
messages_db.pop(message_id)
return f"Message ID={message_id} deleted!"
except IndexError:
raise HTTPException(status_code=404, detail="Message not found")
Вы также можете использовать библиотеку from starlette import status. В этом случае код 404 ошибки будет выглядеть следующим образом:
status_code=status.HTTP_404_NOT_FOUND
Преимущество данного метода в том, что мы можем видеть подсказки статусов в редакторах кода:
FastAPI предоставляет тот же starlette.status под псевдонимом fastapi.status для удобства разработчика. Но его источник - это непосредственно Starlette.
В этом разделе мы узнали, что такое ответы и модели ответов и что подразумевается под обработкой ошибок. Мы также узнали о кодах состояния HTTP и о том, почему важно их использовать. Мы обновили наши существующие маршруты, чтобы они возвращали правильный код ответа.
Исходный код этого раздела вы можете посмотреть по этой ссылке на GitHub.
В следующей главе вы познакомитесь с созданием шаблонов приложений FastAPI с помощью Jinja. Сначала познакомимся с основами, необходимыми для запуска и работы с шаблонами Jinja, после чего создадим пользовательский интерфейс, используя свои знания в области шаблонов для нашего простого приложения.
На всякий случай
except IndexError:Мы используем ошибку индекса только потому, что по созданной нами архитектурой мы берем месаги из листа по индексу