Как стать автором
Поиск
Написать публикацию
Обновить

HTTP status code и что может пойти не так

Уровень сложностиПростой
Время на прочтение5 мин
Количество просмотров1.6K
Аналитик начинает погружение в задачу
Аналитик начинает погружение в задачу

Краткий гайд по наведению порядка HTTP status code и тому, как действовать если реальность становится по-настоящему пугающей.

Представим совершенно невероятную ситуацию: компания-стартап почувствовала потребность в системном аналитике и наняла своего первого специалиста. Знакомство с командой прошло позитивно, аналитик получил все необходимые доступы сразу. Он  изучает продукт компании и получает первую задачу: спроектировать новый API endpoint с применением архитектурного стиля REST. 

Он запускает несколько методов… и дальше начинает происходить что-то сверхъестественное:

  • 200 OK оказался не тем, чем кажется, и содержит в теле описание ошибки; 

  • 500 Internal Server Error отображается вместо ошибки клиента;

  • документации нет, как и обоснования выбора того или иного кода ответа.

В дверь аналитика кто-то постучал.

В этой статье мы разберём примеры отхождения от REST-практик и попытаемся сформировать подход, который поможет шаг за шагом навести порядок в API. Берём с собой блокнот, ручку, фонарик и начинаем писать бестселлер выявлять расхождение с REST-практиками.

Шаг 1. Документация

Первый документ, который необходимо держать под рукой – это Раздел 15 Спецификации RFC 9110HTTP Semantics (2022).

Документ поведает базу – категорий состояний кодов ответа сервера всего пять:

1xx

Запрос получен, идёт обработка.

2xx

Запрос выполнен успешно.

3xx

Чтобы завершить запрос следуйте подсказке (например, перейти по ссылке).

4xx

Ошибка на стороне клиента.

5xx

Ошибка на стороне сервера.

Какие из них рекомендованы в RESTful API, можно посмотреть тут и тут (не официальная документация, а шпаргалка). Мы пропустим Info и Redirection и, обойдёмся необходимым минимумом.

Шаг 2. Проводим исследование 

Теперь пришло время определить масштабы бедствия. Проходимся по основным методам и сверяем запросы/ответы, выявляем закономерности. Будем использовать браузер (F12 + Network и далее Headers – запросы, а Response для ответов).
Представим, что у нас приложение по управлению онлайн магазином со следующими функциональностями:

  • Просмотр Карточки товара.

  • Создание Карточки товара.

  • Редактирование Карточки товара.

Примеры типовых несоответствий практикам REST:

  • Просмотр Карточки товара. 

    • Метод используется для просмотра данных, нет чувствительных данных в запросе, сам запрос не превышает 2000 символов, но используется POST …  getSubject, в ответ приходит 200 OK.

  • Создание Карточки товара. 

    • В ответ на метод создания ресурса POST … subjectsList приходит 200 OK.

    • Ответы на 400 Bad Request не содержат информации о поле, в котором была допущена ошибка.

    • Допустим, мы можем создавать дубли товаров (т.е. c одинаковым полем “name”). В ответ мы получили 500 Internal server error. Описания поля с ошибкой в этом случае не предусмотрено.

  • Редактирование Карточки товара.

    • В ответ на PUT … Subjects/{id} приходит 409 Conflict без указания поля в котором находится ошибка.

    • Допустимо изменение id.

Фиксируем наши находки, маркируем их как результат AS IS и двигаемся дальше. Примеры ниже.

1. Метод: Просмотр карточки товара

Проблематика

1. Использование небезопасного метода без предпосылок.
2. Нарушение принципа безопасности и идемпотентности.

Метод

POST … getSubject

Описание

Метод для получения карточки по id

Тело запроса

{“id”: 1}

200

OK

2. Метод: Создание карточки товара

Проблематика

1. Ответ не содержит информации о создании ресурса.
Нарушение принципа единого интерфейса
2. Нецелевое использование 500 Internal Server Error.
Нарушение принципа self-descriptive messages

Метод

POST … subjectsList

Описание

Метод для создания карточки товара

Тело запроса

{"name": "new-subject-name"}

200

OK 

500

Internal Server Error

3. Метод: Редактирование карточки товара

Проблематика

1. Ответ не содержит описания поля, в котором находится ошибка.
Нарушение принципа: self-descriptive messages
2. Метод позволяет заменить id.
Нарушение принципа идемпотентности.

Метод

PUT … Subjects/{id}

Название

Редактирование карточки товара

Описание

Метод для создания карточки товара

Тело запроса

{"id": 1, "name": "new-subject-name"}

200

OK

Шаг 3. Успешные статус-коды

Попробуем переработать существующую концепцию. 

  • Просмотр Карточки товара. Намечаем, что неплохо перевести POST …  getSubject в GET … v1/Subjects/{id}, и оставить 200 OK в соответствии с гайдом

  • Создание Карточки товара. Ответ POST … v1/Subjects корректируем на 201 Created, потому что запрос был успешно обработан, и в результате был создан новый ресурс (201 Created по гайду).

  • Редактирование Карточки товара. Ничего не меняем, оставляем 200 OK поскольку создания нового ресурса не происходит. Однако, уберём возможность редактировать id.

Шаг 4. Ошибки Клиента

Определимся с тем, что может пойти не так на стороне Клиента. 

  • Создание карточки товара:

    • 400 Bad Request подходит для замены 500 Internal server error. Например, мы не указали количество товара. Обязательно указываем поле, непрошедшее валидацию в теле ответа.

    • 409 Conflict в ситуации, когда например мы Создаем/Редактируем карточку товара и вводим наименование уже существующего товара, а дубли в нашей системе запрещены. Как и ранее, в тексте ошибки указываем на поле с некорректными данными.

  • Редактирование карточки товара. Забираем уже обозначенные выше ошибки:

    • 400 Bad Request валидация одного из полей завершилась ошибкой.

    • 409 Conflict для дублей, как и в карточке создания.

Шаг 5. Ошибки Сервера

Определим, что ошибка сервера теперь не имеет отношения к валидации полей:

  • Создание Карточки товара. 

    • 500 Internal Server Error – базовая ошибка сервера. Например, в ходе выполнения любого из запросов произошла непредвиденная ошибка сервера.

Шаг 6. Подготовка описания API

Теперь нам необходимо подготовить фактуру для будущего обсуждения. У нас должен получиться черновик  с видением TO BE (см. Пример ниже). В ходе обсуждения можно будет также узнать почему в компании существовал подход, используемый ранее, почему REST считается ему хорошей альтернативой, а ещё – глубже понять техническую реализацию проекта.

1. Метод: Просмотр карточки товара

Метод

GET … v1/Subjects/{id}

Название

Просмотреть карточку товара

Описание

Метод для получения карточки по id

200

OK

500

Internal Server error

2. Метод: Создание карточки товара

Метод

POST … v1/Subjects

Название

Создать карточку товара

Описание

Метод для создания карточки товара

201

Created

400

Bad Request

Тело ответа

{
"error": "Validation failed",
"details": [
{
"field": "quantity",
"message": "Quantity field is required"
}
]
}

409

Conflict

Тело ответа

{
"error": "Conflict",
"details": [
{
"field": "name",
"message": "An item with this name already exists"
}
]
}

500

Internal Server Error

Тело ответа

{
"error": "Internal server error",
"details": [
{
"message": "An unexpected error occurred while processing your request"
}
]
}

3. Метод: Редактирование карточки товара

Метод

PUT … v1/Subjects

Название

Редактировать карточку товара

Тело ответа

Метод для редактирования карточки товара

409

Conflict

Тело ответа

{
"error": "Conflict",
"details": [
{
"field": "name",
"message": "An item with this name already exists"
}
]
}

Заключение

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

И самое важное – не забывать, что, работая над документацией, мы не следуем по кругу – мы переходим на новый виток ;)

Теги:
Хабы:
-6
Комментарии0

Публикации

Ближайшие события