Каков соответствующий ответ с кодом состояния HTTP для общего неудачного запроса (не ошибки)?

109

Я создаю RESTful API, который будет обрабатывать ряд взаимодействий с пользователем, включая размещение заказов с использованием сохраненных кредитных карт.

В случае успешного заказа я возвращаю 200 OK, а в случае, если запрос заказа неправильный или недействительный, я возвращаю 400 Bad Request. Но что мне вернуть, если возникла проблема во время фактического оформления заказа?

  1. Заказ POSTS клиента на сервер для пользовательского ресурса. Если пользователь не существует, возвращается 404 Not Found.
  2. Формат заказа и информация проверены. Если неверно, возвращается 400 Bad Request.
  3. Заказ обработан. Если заказ успешен, для заказа возвращается 201 Created. Если обнаружена непредвиденная ошибка, возвращается ошибка сервера 500.

Последний шаг - проблема - что мне вернуть, если заказ не выполнен по какой-либо другой причине? Возможные сценарии могут включать:

  • Товар распродан
  • Достигнут максимальный лимит заказа пользователя
  • Сбой транзакции по кредитной карте (недостаточно средств и т. Д.)

Это не кажется подходящим ни для 400, ни для 500. Во всяком случае, я мог бы видеть это как 400, если нет лучшего кода - запрос был недействительным в соответствии с бизнес-правилами. Это просто не кажется точным.

Изменить: также нашел это существующее обсуждение той же темы. Все ответы там, похоже, указывают на использование кодов состояния для этого типа нарушения, с некоторыми обсуждениями использования расширения 400, 409 или 422.

Raelshark
источник
8
Мне нравится «422 unprocessable entity» для ошибок проверки. И использовал бы его для приведенных выше примеров, включил бы сообщение в ответ с фактической бизнес-проблемой «Продукт продан» и, возможно, добавил бы свои собственные «коды», если клиенту необходимо программно принимать различные решения на основе ответа
house9
прежде чем перейти к 422, подумайте, поддерживаете ли вы возможности WebDAV
Мбитхи Мбити

Ответы:

90

Вы должны использовать 400 для бизнес-правил. Не возвращайте 2xx, если заказ не был принят. HTTP - это протокол приложения, никогда не забывайте об этом. Если вы вернете 2xx, клиент может предположить, что заказ был принят, независимо от любой информации, которую вы отправляете в теле.


Из Поваренной книги веб-служб RESTful :

Одной из распространенных ошибок, допускаемых некоторыми веб-службами, является возврат кода состояния, отражающего успех (коды состояния от 200 до 206 и от 300 до 307), но включающего тело сообщения, описывающее состояние ошибки. Это предотвращает обнаружение ошибок программным обеспечением, поддерживающим HTTP. Например, кеш будет хранить его как успешный ответ и передавать его последующим клиентам, даже если клиенты могут сделать успешный запрос.

Я оставлю вам выбор между 4xx и 5xx, но вы должны использовать код состояния ошибки.

Макс Торо
источник
1
Есть ли у вас какие-либо примеры или ссылки на этот подход в сравнении с другим? И ваш, и ответ Widor имеют смысл, один с точки зрения HTTP как протокола приложения, а другой, поскольку он предназначен исключительно для цели передачи. Спецификация определяет его как «протокол уровня приложения», что немного расплывчато. Изучая это, я также видел как точки зрения, так и примеры в Интернете.
Raelshark
это правда.
Ён Хён Ю
2
Вы имеете в виду: «Вы должны использовать 4xx для бизнес-правил»?
Yawar
28

Вы должны использовать 4xx для ошибки клиента, если клиент может изменить запрос, чтобы обойти ошибку. Используйте 5xx для ошибки сервера, которую клиент не может исправить.

Распроданный товар был бы ошибкой сервера. Клиент не может каким-либо образом изменить запрос, чтобы обойти ошибку. Вы могли бы переключиться на другой продукт, но разве это не новый запрос?

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

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

Пол Морган
источник
6
Если лимит заказа достигнут, не должен ли клиент предупредить об этом пользователя и позволить ему соответствующим образом изменить свой запрос? Похоже на ошибку 4xx. То же самое и с продаваемым товаром. Ошибки 5xx предназначены для ошибок, которые вызваны каким-либо образом неисправной системы, а не для действий, запрещенных бизнес-правилом.
carlin.scott
7
Я согласен с комментарием выше. Ошибки 5xx возникают при возникновении проблем на сервере. Ошибки 4xx для бизнес-правил.
Merc
21

Тип ошибки:

4×× Client Error

Код ошибки:

422 Unprocessable Entity

Сервер понимает тип содержимого объекта запроса (следовательно, код состояния 415 Unsupported Media Type не подходит), и синтаксис объекта запроса правильный (таким образом, код состояния 400 Bad Request не подходит), но не смог обработать содержащиеся инструкции.

Например, это состояние ошибки может возникнуть, если тело запроса XML содержит правильно сформированные (т. Е. Синтаксически правильные), но семантически ошибочные инструкции XML.

https://httpstatuses.com/422

заикающийся
источник
16

Я знаю, что это старый вопрос, но сегодня я задал тот же вопрос. Если у моего пользователя заканчиваются кредиты, какой код статуса должен вернуть мой REST API?

Я склоняюсь к 402 Payment Required:

Согласно Википедии :

Зарезервировано для использования в будущем. Первоначальное намерение состояло в том, чтобы этот код можно было использовать как часть какой-либо формы цифровых денег или схемы микроплатежей, но этого не произошло, и этот код обычно не используется. Google Developers API использует этот статус, если конкретный разработчик превысил дневной лимит запросов.

И действительно , они делают :

ТРЕБУЕТСЯ ОПЛАТА (402)

  • Достигнут предел дневного бюджета, установленный разработчиком.
  • Запрошенная операция требует больше ресурсов, чем позволяет квота. Оплата требуется для завершения операции.
  • Запрошенная операция требует какой-либо оплаты от аутентифицированного пользователя.
Бенджамин
источник
Это наиболее продуманный и логичный ответ.
GTodorov
5

Как насчет 424 Failed Dependency? Спецификация описывает это как:

Метод не может быть выполнен для ресурса, поскольку запрошенное действие зависело от другого действия, и это действие не удалось.

Но есть еще такое определение :

Код состояния 424 определен в стандарте WebDAV и предназначен для случая, когда клиенту необходимо изменить то, что он делает - сервер здесь не испытывает никаких проблем.

Вы можете сообщить клиенту (или сделать вид), что у вас есть внутренние действия, которые должны создать заказ и вычесть баланс, и что одно из этих действий не удалось, хотя и по вполне уважительным причинам, и именно поэтому запрос не удался.

Насколько я понимаю, «действие» - довольно широкий термин, и его можно использовать в самых разных ситуациях, включая недостаточный запас, недостаточный кредит или ночь на складе.


Другой вариант 422 Unprocessable Entity:

Сервер понимает тип содержимого объекта запроса (следовательно, код состояния 415 Unsupported Media Type не подходит), и синтаксис объекта запроса правильный (таким образом, код состояния 400 Bad Request не подходит), но не смог обработать содержащиеся инструкции.

Например, это состояние ошибки может возникнуть, если тело запроса XML содержит правильно сформированные (т. Е. Синтаксически правильные), но семантически ошибочные инструкции XML.

Попытка запросить товар, которого нет в наличии, или когда у вас недостаточно средств на счете, может считаться ошибкой на семантическом уровне.

MozDev говорит, что это указывает на ошибку на стороне клиента, а именно: клиент не должен повторять этот запрос без изменений.

Loopback 4 использует 422, когда проверка ввода не выполняется.


Возможно, недостаточный запас или вечеринка на складе можно рассматривать как временное состояние, поэтому запрос можно будет повторить позже. На эту ситуацию может указывать503 Service Unavailable

В настоящее время сервер не может обработать запрос из-за временной перегрузки или планового обслуживания, которые, вероятно, будут устранены после некоторой задержки.

Сервер МОЖЕТ отправить поле заголовка Retry-After, чтобы предложить клиенту подходящее время ожидания перед повторной попыткой запроса.

Joeytwiddle
источник
Ничего из этого не связано с оплатой. Я выберу 402 из предыдущего ответа!
GTodorov
2

Я не думаю, что 400 можно использовать для всех бизнес-сценариев. Его можно использовать для проверки ввода основных данных. Кроме того, нам, возможно, будет сложно вовремя уместить другую бизнес-логику в этот код ошибки. Ошибки, обрабатываемые этим, в основном являются ошибками времени разработки, с которыми разработчик может столкнуться во время кодирования клиента.

Допустим, все параметры верны, и допустим, мы передаем в запрос номер учетной записи пользователя.

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

Я бы посоветовал нам использовать 403 с соответствующим сообщением об ошибке в этих сценариях.

Другим возможным кодом ошибки может быть конфликт 409. Но это используется в сценариях, когда ресурс находится в согласованном состоянии.

Раджендер Сайни
источник
0

Я использую 406 Not Acceptable.

Вот список 4xx:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585
Махмуд Залт
источник
8
Хотя название кода состояния 406 само по себе может показаться точным, вы должны знать, что каждый код состояния имеет достоверное текстовое описание. Описание кода состояния 406 не подходит для данного случая. См. , Например, httpstatuses.com/406 .
Zero3
1
@ Zero3 прав, этот код означает, что тип ответа неприемлем, так как существует несоответствие между заголовками Accept, отправленными от клиента, и типами MediaType, отправленными конечной точкой, например application / json vs. text / plain
Грегор