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

Спецификация HTTP/1.1 (RFC 2616) имеет следующее значение в отношении значения кода состояния 400 "Плохой запрос" (§10.4.1):

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

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

Примеры:

6 ответов

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Спасибо Виш

Это сложно.

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

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

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

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

Запрос работал нормально, он попал в правила вашего приложения, клиент все сделал правильно, 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 инструкции форма.

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

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

Синтаксис простого URL - {протокол +: + // + сервер +: + порт}. Согласно этому " http://www.google.com/" является синтаксически правильным.

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

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

В моем случае:

Я получаю 400 неверных запросов, потому что я установил content-typeнеправильно. Я изменил тип контента, после чего смог успешно получить ответ.

Перед (выпуск):

ClientResponse response = Client.create().resource(requestUrl).queryParam("noOfDates", String.valueOf(limit))
                .header(SecurityConstants.AUTHORIZATION, formatedToken).
header("Content-Type", "\"application/json\"").get(ClientResponse.class);

После (исправлено):

ClientResponse response = Client.create().resource(requestUrl).queryParam("noOfDates", String.valueOf(limit))
                .header(SecurityConstants.AUTHORIZATION, formatedToken).
header("Content-Type", "\"application/x-www-form-urlencoded\"").get(ClientResponse.class);
Другие вопросы по тегам