REST HTTP коды состояния для неудачной проверки или неверного дубликата

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

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

Я просмотрел http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html но ни один из них не кажется правильным.

Есть ли распространенная практика при отправке кодов состояния?

11 ответов

Решение

Для ошибки проверки ввода: 400 Bad Request + ваше необязательное описание. Это предлагается в книге " RESTful Web Services". Для двойной подачи: 409 конфликтов


Обновление июнь 2014

Соответствующей спецификацией был RFC2616, который давал использование 400 (Bad Request) довольно узко

Сервер не может понять запрос из-за неправильного синтаксиса

Таким образом, можно утверждать, что это неуместно для семантических ошибок. Но не больше; с июня 2014 года соответствующий стандарт RFC 7231, который заменяет предыдущий RFC2616, дает более широкое использование 400 (Bad Request) как

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

  • Ошибка проверки: 403 Запрещено ("Сервер понял запрос, но отказывается его выполнить"). Вопреки распространенному мнению, RFC2616 не говорит "403 предназначен только для неудачной аутентификации", но "403: я знаю, что вы хотите, но я не буду этого делать". Это условие может или не может быть связано с аутентификацией.
  • Попытка добавить дубликат: 409 Conflict ("Не удалось выполнить запрос из-за конфликта с текущим состоянием ресурса.")

Вы обязательно должны дать более подробное объяснение в заголовках и / или теле ответа (например, с пользовательским заголовком - X-Status-Reason: Validation failed).

Я рекомендую код состояния 422 "Необработанный объект".

11.2. 422 необработанного объекта

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

200,300, 400, 500 все очень общие. Если вы хотите универсальный, 400 в порядке.

422 используется все большим количеством API, и даже используется Rails из коробки.

Независимо от того, какой код статуса вы выбираете для своего API, кто-то не согласится. Но я предпочитаю 422, потому что считаю "400 + текстовый статус" слишком общим. Кроме того, вы не используете JSON-готовый парсер; Напротив, 422 с ответом JSON очень явный, и может быть передано много информации об ошибках.

Говоря об ответе JSON, я склонен стандартизировать ответ об ошибках Rails для этого случая, а именно:

{
    "errors" :
    { 
        "arg1" : ["error msg 1", "error msg 2", ...]
        "arg2" : ["error msg 1", "error msg 2", ...]
    }
}

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

Дубликат в базе данных должен быть 409 CONFLICT,

Я рекомендую использовать 422 UNPROCESSABLE ENTITY для ошибок проверки.

Я дам более подробное объяснение кодов 4xx здесь: http://parker0phil.com/2014/10/16/REST_http_4xx_status_codes_syntax_and_sematics/

200

Тьфу... (309, 400, 403, 409, 415, 422)... множество ответов, пытающихся угадать, поспорить и стандартизировать, какой код возврата является лучшим для успешного http-запроса, но неудачного вызова rest.

Неправильно смешивать коды протокола HTTP и результаты REST.

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

Коды возврата HTTP связаны с HTTP Request сам. Вызов REST выполняется с использованием запроса протокола передачи гипертекста, и он работает на более низком уровне, чем сам вызванный метод REST. REST является концепцией / подходом, и его выходные данные являются бизнес / логическим результатом, в то время как код результата HTTP является транспортным.

Например, возвращение "404 Не найдено" при вызове /users/ вызывает путаницу, поскольку это может означать:

  • Неверный URI (HTTP)
  • Пользователи не найдены (REST)

"403 Запрещено / Доступ запрещен" может означать:

  • Требуется специальное разрешение. Браузеры могут справиться с этим, спросив пользователя / пароль. (HTTP),
  • Неправильные разрешения доступа настроены на сервере. (HTTP),
  • Вам необходимо пройти проверку подлинности (REST)

И этот список может продолжаться с "500 Server error" (ошибка, вызванная HTTP-ошибкой Apache/Nginx или ошибка бизнес-ограничения в REST), или другими ошибками HTTP и т. Д.

Из кода трудно понять, что было причиной сбоя, сбоя HTTP (транспорта) или сбоя REST (логического).

Если HTTP-запрос физически был выполнен успешно, он всегда должен возвращать 200 кодов, независимо от того, найдены записи или нет. Потому что ресурс URI найден и обработан сервером http. Да, он может вернуть пустой набор. Можно ли получить пустую веб-страницу с 200 в результате http, верно?

Вместо этого вы можете вернуть 200 HTTP-код с некоторыми опциями:

  • "ошибка" объекта в JSON, если что-то пойдет не так
  • Пустой массив / объект JSON, если запись не найдена
  • Флаг результата / успеха bool в сочетании с предыдущими опциями для лучшей обработки.

Кроме того, некоторые интернет-провайдеры могут перехватить ваши запросы и вернуть вам http-код 404. Это не означает, что ваши данные не найдены, но что-то не так на транспортном уровне.

Из вики:

В июле 2004 года британский телекоммуникационный провайдер BT Group развернул систему блокировки контента Cleanfeed, которая возвращает ошибку 404 при любом запросе контента, который, по мнению Internet Watch Foundation, считается потенциально незаконным. Другие интернет-провайдеры возвращают ошибку HTTP 403 "Запрещено" при тех же обстоятельствах. Практика использования фальшивых ошибок 404 в качестве средства сокрытия цензуры была также отмечена в Таиланде и Тунисе. В Тунисе, где цензура была жестокой до революции 2011 года, люди узнали о природе фальшивых ошибок 404 и создали воображаемого персонажа по имени "Аммар 404", который представляет "невидимого цензора".

Почему бы просто не ответить чем-то вроде этого?

{
  "result": false,
  "error": {"code": 102, "message": "Validation failed: Wrong NAME."}
}

Google всегда возвращает 200 в качестве кода состояния в своем API геокодирования, даже если запрос логически не выполняется: https://developers.google.com/maps/documentation/geocoding/intro

Адаптер Ember-Data ActiveRecord ожидает 422 UNPROCESSABLE ENTITY быть возвращенным с сервера. Итак, если ваш клиент написан на Ember.js, вы должны использовать 422. Только тогда DS.Errors будет заполнен возвращенными ошибками. Конечно, вы можете изменить 422 на любой другой код в вашем адаптере.

Код состояния 304 Не изменен также сделает приемлемый ответ на дубликат запроса. Это похоже на обработку заголовка If-None-Match используя тег сущности.

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

Если вы хотите обрабатывать повторный запрос как предупреждение или уведомление, а не как ошибку, код состояния ответа 304 Не модифицировано и Content-Location заголовок, идентифицирующий существующий ресурс, будет таким же действительным. Когда целью является просто обеспечение существования ресурса, повторный запрос будет не ошибкой, а подтверждением. Запрос не является неправильным, но просто избыточен, и клиент может ссылаться на существующий ресурс.

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

Я пришел к выводу, что нужно попытаться следовать этому правилу: если это указывает на ошибку разработчика клиента, используйте (Bad Request). В противном случае, если клиент вообще не проверяется, если глупый пользователь вводит неверные данные, используйте (Unprocessable Entity). Если вы сомневаетесь, предпочтите или, возможно, используйте тот, который проще в реализации.

Это помогает разработчику узнать, кто на самом деле допустил ошибку, будь то он сам или пользователь.

Под тупым пользователем я подразумеваю пользователя, не разбирающегося в технических вопросах. Злоумышленник здесь не имеет значения: если бы вас это беспокоило, вы бы вообще не использовали коды состояния HTTP. :)

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

Это также может быть полезно для улучшения логики ветвления. Например, в контексте REST API предположим, что у вас есть конечная точка ответа на опрос с возможными методами POST и PATCH. В этом случае, если клиент отправляет недопустимый запрос POST, вы можете отправить URI нового ресурса обратно вLocationзаголовок, когда код состояния422, но не для400.

Примеры из реального мира, безусловно, сложнее, но это должно отлично работать, ИМХО.

406 - Неприемлемо

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

Я думаю, что у каждого будет свое мнение по этому поводу, потому что мы все ссылались на коды статуса в разных контекстах. Но важно то, что наиболее широко принято и известно. 400 известен и принимается как ответ на ошибку проверки, а 409, как следует из названия, является конфликтом. Если мы говорим, что 400 не подходит для ошибки проверки, потому что сервер понял запрос, тогда подумайте о том, что кто-то задает вам вопрос, который вы понимаете по словам, но вы могли бы ответить и сказать: «О, это неверный вопрос» или «Это неправильный вопрос». не имеет смысла», поэтому то, что вы поняли слова, не означает, что они имеют смысл. Иначе мы можем говорить об этом весь день.

Другие вопросы по тегам