Как обрабатывать ошибки в endpoint
Что проверяют
Понимаете ли вы, что обработка ошибок это единый контракт API, а не try/except в каждой функции. Следом обычно спрашивают, как вы отличаете ошибку клиента от ошибки сервера и что при этом попадает в лог, а что в ответ.
Как отвечать
Опишите три слоя на примере FastAPI, для Django REST Framework и Flask логика та же:
- доменные исключения: сервисный слой бросает свои классы (
NotFoundError,ConflictError,PermissionDenied) и ничего не знает про HTTP; - централизованный обработчик:
@app.exception_handler(NotFoundError)превращает исключение в статус и тело ответа. В DRF это функция в настройкеEXCEPTION_HANDLER, во Flask@app.errorhandler. Эндпоинт остаётся чистым; - единый формат тела: например, Problem Details по RFC 9457 (
type,title,status,detail), плюс машинный код ошибки, по которому фронтенд выбирает сообщение; - статусы по смыслу: 400 некорректный запрос, 401 нет аутентификации, 403 нет прав, 404 нет ресурса, 409 конфликт состояния, 422 ошибка валидации (FastAPI отдаёт её сам через
RequestValidationError), 429 превышен лимит, 500 непредвиденная ошибка, 503 недоступна зависимость; - логирование: непредвиденные исключения пишутся через
logger.exceptionс трассировкой и идентификатором запроса, который возвращается клиенту в ответе. Дальше Sentry или аналог.
Отдельно скажите про тесты: pytest и TestClient проверяют не только код ответа, но и тело ошибки, иначе контракт незаметно разъедется.
Где спотыкаются
Отдают клиенту str(e) на 500. Туда попадают SQL, пути к файлам и детали инфраструктуры, а это утечка информации.
Возвращают 200 с полем error в теле. Клиенты, прокси и мониторинг считают такой ответ успешным, и ошибки становятся невидимыми.
Путают 401 и 403 или ловят except Exception в каждом эндпоинте и глушат ошибку без записи в лог, после чего причину сбоя уже не восстановить.