HTTP 400 (неверный запрос) для логической ошибки, а не искаженный синтаксис запроса

спецификация HTTP/1.1 (RFC 2616) имеет следующие значения: status code 400, Bad Запрос (§10.4.1):

Запрос не мог быть понят сервер из-за неправильного синтаксиса. Клиент НЕ ДОЛЖЕН повторять запросить без изменений.

В наши дни, похоже, существует общая практика среди нескольких API-интерфейсов на основе HTTP, чтобы использовать 400 для обозначения логической, а не синтаксической ошибки с запросом. Я предполагаю, что API делают это, чтобы различать 400 (клиентский) и 500 (сервер- индуцированный). Допустимо или неверно использовать 400 для обозначения несинтаксических ошибок? Если это приемлемо, есть аннотированная ссылка на RFC 2616, которая обеспечивает более глубокое понимание предполагаемого использования 400?

Примеры:

Ответ 1

Состояние 422 (RFC 4918, раздел 11.2) приходит на ум:

Код состояния 422 (необработанная сущность) означает, что сервер понимает тип содержимого объекта запроса (следовательно, код статуса 415 (неподдерживаемый тип носителя) является неуместным), и синтаксис объекта запроса является правильным (таким образом, 400 (Bad Request) неуместен), но не смог обработать содержащиеся инструкции. Например, это условие ошибки может возникнуть, если тело запроса XML содержит правильно сформированные (т.е. Синтаксически правильные), но семантически ошибочные инструкции XML.

Ответ 2

Начиная с этого момента, последний проект спецификации HTTPbis, который предназначен для замены и удаления устаревшего RFC 2616, состояния:

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

Это определение, хотя, конечно, по-прежнему подвержено изменениям, ратифицирует широко используемую практику ответа на логические ошибки с 400.

Ответ 3

HTTPbis рассмотрит формулировку 400 Bad Request, чтобы он также охватывал логические ошибки. Таким образом, 400 будет включать 422.

От https://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-18#section-7.4.1
"Сервер не может или не будет обрабатывать запрос из-за ошибки клиента (например, искаженного синтаксиса)"

Ответ 4

Можно утверждать, что наличие неверных данных в вашем запросе является синтаксической ошибкой, даже если ваш фактический запрос на уровне HTTP (строка запроса, заголовки и т.д.) Синтаксически допустим.

Например, если веб-служба Restful задокументирована как принимающая POST с пользовательским типом содержимого XML application/vnd.example.com.widget+xml, и вы вместо этого отправляете какой-то неоправданный простой текст или двоичный файл, это кажется разумным для обработки это как синтаксическая ошибка - ваше тело запроса не в ожидаемой форме.

Я не знаю ни одного официального упоминания, подтверждающего это, хотя, как обычно, дело доходит до интерпретации RFC 2616.

Обновление: обратите внимание на пересмотренную формулировку в RFC 7231 §6.5.1:

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

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

Сервер не может понять запрос из-за неправильного синтаксиса. Клиент НЕ ДОЛЖЕН повторять запрос без изменений.

Ответ 5

Несмотря на то, что я использовал 400 для представления логических ошибок, я должен сказать, что возвращение 400 в этом случае неверно из-за того, как читается спецификация. Вот почему я так думаю, логическая ошибка может заключаться в том, что связь с другим объектом терпит неудачу или не выполняется, и внесение изменений в другой объект может привести к тому, что тот же самый тег будет передан позже. Подобно попытке (полностью гипотетическому) добавить сотрудника в качестве члена отдела, когда этот сотрудник не существует (логическая ошибка). Добавление сотрудника как запрос участника может завершиться неудачей, потому что сотрудник не существует. Но тот же самый точный запрос может пройти после того, как сотрудник был добавлен в систему.

Только мои 2 цента... Нам нужны юристы и судьи для интерпретации языка в RFC в эти дни:)

Спасибо, Вишь

Ответ 6

На серверах Java EE возвращается 400, если ваш URL-адрес относится к несуществующей "веб-папке". Это синтаксическая ошибка? Зависит от того, что вы подразумеваете под синтаксической ошибкой. Я бы сказал, да.

В английских синтаксических правилах задаются определенные отношения между частями речи. Например, "Боб женится на Мэри" синтаксически корректен, потому что он следует шаблону {Noun + Verb + Noun}. В то время как "Боб брака Мэри" будет синтаксически неправильным, {Noun + Noun + Существительное}.

Синтаксис простого URL-адреса {protocol +: +//+ server +: + port}. В соответствии с этим " http://www.google.com:80" синтаксически корректно.

Но как насчет "abc://www.google.com: 80"? Кажется, что он соответствует той же схеме. Но действительно это синтаксическая ошибка. Зачем? Поскольку "abc" не является протоколом DEFINED.

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

Ответ 7

Это сложно.

Я думаю, нам следует;

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

  2. Вернуть коды диапазона ошибок, когда ожидаемая мутация не произошла, т.е. УДАЛИТЬ не произошло или PUT ничего не изменило. Однако POST более интересен, потому что в спецификации сказано, что его следует использовать для создания ресурсов в новом месте или просто для обработки полезной нагрузки.

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

Запрос работал нормально, он попал в правила вашего приложения, клиент все сделал правильно, ETags совпали и т.д. И т.д.

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

Возможно, вы разработали это.

PUT { updated members list } /marketing/members

Возвращение кода успеха будет означать, что "замена" ресурса сработала; GET на ресурсе будет отражать ваши изменения, но это не так.

Так что теперь вы должны выбрать подходящий отрицательный код HTTP, и это сложная часть, так как коды строго предназначены для протокола HTTP, а не для вашего приложения.

Когда я читаю официальные коды HTTP, эти два выглядят подходящими.

Код состояния 409 (Конфликт) указывает, что запрос не может быть выполнен из-за конфликта с текущим состоянием целевого ресурса. Этот код используется в ситуациях, когда пользователь может разрешить конфликт и повторно отправить запрос. Сервер ДОЛЖЕН генерировать полезную нагрузку, которая включает в себя достаточно информации, чтобы пользователь мог распознать источник конфликта.

А также

Код состояния 500 (Внутренняя ошибка сервера) указывает, что сервер обнаружил непредвиденное состояние, которое не позволило ему выполнить запрос.

Хотя мы традиционно считали 500 как необработанное исключение: -/

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

С этим дизайном легче иметь дело.

PUT { membership add command } /accounts/groups/memberships/instructions/1739119

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

POST больше похож на последний PUT на новое место. POST позволяет обрабатывать сообщения любого типа на сервере, что открывает проекты, которые говорят что-то вроде "Действие успешно завершилось неудачей".

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

В случае POST вы возвращаете 200 или 201 вместе с сообщением об отказе, зависит от того, был ли создан новый ресурс и доступен ли он для GET в другом месте или нет.

Учитывая все вышесказанное, я был бы склонен разрабатывать API, которым требуется меньше PUT, возможно, просто обновлять поля данных, а действия и вещи, которые вызывают правила и обработку или просто имеют более высокую вероятность ожидаемых сбоев, могут быть разработаны для POST-инструкции форма.