Привет, Хабр! Меня зовут Екатерина Саяпина, я Product Owner платформы МТС Exolve. Коды ошибок — последнее, что хочет видеть разработчик в ответе API. И означают они одно из двух: либо есть проблема в запросе, либо что-то сломалось на стороне API.

В любом случае трафик останавливается: нужно найти причины и решения. И коды ошибок в этом случае — полезный диагностический элемент. Сегодня я расскажу про подходы к их обработке и дам пример распространенной классификации.

Коды ошибок: значение

Коды ошибок при ответе API — основной способ, с помощью которого разработчик может сообщить пользователю о проблеме. Они следуют за начальным запросом и представляют собой прямую связь между клиентом и API.

Часто этот шаг не только информирует о сбое, но и помогает запустить процесс отладки. Коды одновременно проясняют ситуацию и уведомляют о предполагаемой неисправности.

Рассмотрим, например, код 401 Unauthorized — Please Pass Token. Здесь очевидна суть сбоя: пользователь не прошел аутентификацию. По нему сразу понятна предполагаемая неисправность — API требует токен, и для предоставления доступа он должен быть передан как часть запроса.

Коды состояния HTTP

Их можно встретить не только при работе с API, но и при обычном просмотре web-страниц. Их можно разделить по группам значений.

1XX — информирование

У диапазона кодов 1XX есть две основные функции. Первая заключается в передаче информации о состоянии протокола подключенных устройств. Например, 101 Switching Protocols — это код, отмечающий, что запрос клиента на изменение протокола с сервера был одобрен. Диапазон 1XX также уточняет состояние первоначального запроса. Код 100 Continue означает, что сервер, получивший от клиента заголовки запроса, ожидает его тело.

2XX — успех

Коды 2XX отмечают ряд удачно завершенных действий и объединяют ответы в определенные коды. Первые три прекрасно демонстрируют этот диапазон:

  • 200 OK — запрос прошел успешно.

  • 201 Created — запрос выполнен, и создан новый ресурс для клиента.

  • 202 Accepted — запрос принят, и обработка началась.

3XX — перенаправление

Коды 3XX полностью соответствуют статусу ресурса или конечной точки и показывают, что для успешного завершения операции нужно выполнить другой запрос, чаще всего по иному URL.

К примеру, 301 Moved Permanently проверяет, действительно ли запрос клиента достиг правильной системы, а также то, что этот запрос и все будущие должны обрабатываться другим URl. Это очень полезно в субдоменах и при перемещении ресурса между серверами.

4XX — ошибка клиента

Серия 4XX самая знаменитая — 404 Not Found показывает неправильно сформированные URL-адреса, и URI и является одним из популярных мемов. Однако в этом диапазоне существуют и другие полезные коды для API.

414 URI Too Long — общий код состояния. Он обозначает, что данные, передаваемые методом GET, слишком длинные и должны быть преобразованы в POST. Также можно укоротить URL-запрос вручную или изменить его структуру.

Другой распространенный код — 429 Too many Requests — используется для реализации механизмов ограничения частоты запросов (rate limiting), чтобы показать попытки клиента одновременно выполнить слишком много запросов. Также может указывать на DDoS-атаку.

5XX — ошибка сервера

Диапазон 5XX зарезервирован для кодов, специально связанных с функциональными возможностями сервера. Например, 502 Bad Gateway означает, что вышестоящий сервер вышел из строя и текущий является шлюзом. Также он дополнительно раскрывает место возникновения сбоя. Есть и менее конкретные коды, указывающие на общие неполадки, например 503 Service Unavailable — сервис недоступен.

Как работать с кодами ошибок

Когда у нас есть четкое представление о кодах состояния HTTP, мы можем проанализировать, какие из них сообщают не только о проблемах, но и о причинах.

Непрозрачные коды ошибок бесполезны. Представим, что вы пытаетесь отправить запрос GET к API, который обрабатывает инвентарь цифровой музыки. Вы передаете данные в API, регулярно принимающий ваш трафик, отправляете правильные учетные данные для авторизации и аутентификации и ждете ответ сервера.

Вместо него вам прилетает 400 Bad Request без дополнительных данных. Этот код находится в диапазоне 4XX и показывает, что проблема была на стороне клиента. Подробностей в нем нет — только скудные сведения о «некорректном запросе». Этот пример иллюстрирует случай, когда код ошибки не несет практической пользы.

Хорошие сообщения об ошибках должны включать:

  • Код состояния HTTP, позволяющий легко определить источник и область проблемы.

  • Идентификатор внутренней ссылки для обозначения ошибок, специфичных для документации. В некоторых случаях он может дополнить HTTP-код, предоставляя ссылку на конкретную страницу, где эта проблема описывается подробно.

  • Сообщение с контекстом, причиной и общим решением возникшей ошибки.

В примере выше 400 Bad Request ничего не означает, хотя код должен давать дополнительный контекст. Один из способов добавить его — передать информацию в теле ответа на языке, общем для самого запроса.

Например, код ошибки 400 Bad Request может легко форматировать в JSON с полезной для клиента информацией:

Конкретный тип сбоя показывает, с чего пользователю начать решение проблемы. Кроме того, он дает внутренний идентификатор ссылки (BR0x0071), по которому ошибку можно найти в документации.

Читабельность

BR0x0071 — это машиночитаемый ссылочный код к примечанию о внутренней ошибке, но пользователю он до сих пор не понятен. Чтобы разобраться в проблеме, ему придется закопаться в документацию. Хорошей практикой в проектировании API является отделение кода ошибки от текстового сообщения.

Это помогает:

  1. Четко различать машинно ориентированные коды ошибок и текстовые пояснения для человека.

  2. Упростить обработку ошибок на стороне клиента. Так разработчики могут использовать error_code для программной обработки, а error_message — для информирования пользователя.

Исправим это и внесем изменения, сохраняя ссылочный номер:

Теперь по ответу понятно, что проблема спряталась в параметрах, и он может приступить к устранению неполадок.

Примеры

Давайте посмотрим коды ошибок в некоторых популярных системах.

Twitter

Twitter API — отличный пример реализации развернутых сообщений об ошибках. Отправим запрос GET, чтобы получить временную шкалу упоминаний:

GET https://api.twitter.com/1.1/statuses/mentions_timeline.json

Нам возвращается такой ответ:

Переданный пользователю код ошибки — 400 Bad Request. Он указывает, что проблема в запросе. Длина нашего контента приемлема, а время ответа находится в пределах нормы. Однако мы видим уникальный код 215 прикрепленным сообщением «неправильные данные аутентификации».

Bing

Чтобы показать сложный код ответа на ошибку, отправим плохо сформированный (по сути нулевой) запрос GET в Bing:

Bing возвращает нам код 1001 вместе с сообщением о том, что параметр отсутствует. Он обозначается как SearchRequestAppId, а переменная HelpUrl передается как ссылка на решение.

В этом случае у нас есть машиночитаемый код ошибки, понятное описание проблемы и ссылка на документацию по ней.

О важности баланса

Как мы видим из примеров, у большей части кодов ошибки нет строгой структуры, и вы сами можете выбирать, на что ссылаться, какие данные выводить и как их отображать. Но общая цель подобных ответов — не только информировать пользователя, но и помогать ему. То же относится и к сбоям API.

Важно добиться баланса — информативности и краткости. Развернутое описание проблемы и данные для ее решения должны сочетаться с легкостью чтения и анализа.

Комментарии (6)


  1. mitix
    05.02.2025 07:49

    Удивлен, что не упомянули Problem Details


    1. dab1818
      05.02.2025 07:49

      ...и более "свежий" Problem Details https://www.rfc-editor.org/rfc/rfc9457.html


  1. savostin
    05.02.2025 07:49

    Холивара ради: должен ли API всегда при ошибке возвращать http status != 200/302 или как в примере возвращать всегда 200, а в теле сообщать о проблемах?


    1. mitix
      05.02.2025 07:49

      Ну а зачем тогда вообще нужны HTTP коды?


    1. space2pacman
      05.02.2025 07:49

      Кому как удобно

      Кто-то API делает с учетом кодов и типов запроса

      Кто-то работает только с 200-ым кодом но с разными типами запросов

      А кто-то вообще только на POST запросах проектирует API


  1. big17
    05.02.2025 07:49

    Как будто бы не совсем точный заголовок статьи. Ожидание, что там будет описано как фронтенд обрабатывает ошибки от REST API