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

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

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

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

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

Ответ 1

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


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

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

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

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

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

Ответ 2

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

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

Ответ 3

Я рекомендую код статуса 422, "Непроцессная сущность" .

11.2. 422 Непроцессная организация

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

Ответ 4

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", ...]
    }
}

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

Ответ 6

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#StatusCodes

Facebook всегда возвращает 200 для успешных HTTP-запросов, даже если запрос REST завершается неудачно: https://developers.facebook.com/docs/graph-api/using-graph-api/error-handling

Это просто, коды состояния HTTP для запросов HTTP. REST API - это Ваш, определите Ваши коды статуса.

Ответ 7

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

Ответ 8

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

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

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

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