REST коди статусу HTTP за невдалу перевірку або недійсний дублікат


825

Я будую додаток з API на основі REST і дійшов до того, що я вказую коди статусу для кожного запиту.

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

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

Чи є загальна практика при надсиланні кодів статусу?



14
Відкрийте httpstatus.es , клацніть правою кнопкою миші >> Pin Tab: P
Salman von Abbas

Відповіді:


779

Для помилки перевірки вводу: 400 Поганий запит + ваш необов'язковий опис. Про це пропонується у книзі " RESTful Web Services ". Для подвійної подачі: 409 Конфлікт


Оновлення червня 2014 року

Відповідною специфікацією раніше був RFC2616 , який давав використання 400 (Bad Request) досить вузько

Сервер не міг зрозуміти запит через неправильний синтаксис

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

сервер не може або не обробляє запит через те, що сприймається як помилка клієнта


3
Так, тіло запиту є частиною синтаксису.
Діамон

62
Поганий запит, безумовно, є найпоширенішою відповіддю на подібне питання. Єдина інша альтернатива - 422 Unprocessable Entity. Він насправді походить від WebDav, але цілком справедливо для повторного використання будь-якого коду статусу, зареєстрованого в IANA.
Даррел Міллер

19
Тож як ви розмежуєте неправильно сформовані дані, які сервер навіть не може розібрати, та помилку перевірки? Клієнт розглядає ці два відповіді абсолютно по-різному. Для перевірки вони, ймовірно, відображатимуть помилки користувачеві. Для справді "неправильно сформованих даних" вони записують помилку, щоб помилка в методі, що генерує запит, могла бути виправлена.
Джош Ное

18
Я не погоджуюся з вашою інтерпретацією RFC7231, хоча в ній зазначено something perceived to be a client error, що всі приклади, наведені в цьому пункті, - це порушення протоколу HTTP, а не логічні помилки: синтаксис, обрамлення, маршрутизація. Таким чином, я вважаю, що специфікація HTTP не дозволяє 400 для невдалої перевірки на рівні програми.
Діма Тиснек

2
чому б не використати об'єкт 422 - не оброблюваний об'єкт? Мені здається більш логічним
java_geek

278
  • Не вдалося перевірити: 403 Заборонено ("Сервер зрозумів запит, але відмовляється його виконати"). Всупереч поширеній думці, RFC2616 не каже, що "403 призначений лише для невдалої аутентифікації", але "403: Я знаю, що ви хочете, але цього не робитиму". Цей стан може бути, а може і не бути результатом автентифікації.
  • Спроба додати дублікат: 409 Conflict ("Запит не вдалося виконати через конфлікт із поточним станом ресурсу.")

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


17
@deamon: Це не специфікація, це Wikipedia, тобто чиясь думка про те, що означають коди статусу HTTP "; зауважте, що на сторінці basicy написано "це те, що означає Apache з 403, це означає IIS з 403", і ніде це не посилається на офіційний RFC. Ви ніби повторюєте "403 означає все, що говорить Apache". НЕ. Фактичний RFC (який є відповідний документ, а нереалізації Apache, а НЕ IIS »реалізації, а не хтось - то чужий реалізації) тут: w3.org/Protocols/rfc2616/rfc2616-sec10.html
Piskvor покинув будівлю

57
"10.4.4 403 Заборонено Сервер зрозумів запит, але відмовляється його виконувати. Авторизація не допоможе, і запит НЕ повинен повторюватися. Якщо метод запиту не був HEAD і сервер бажає оприлюднити, чому запит не виконав буде виконано, він повинен описувати причину відмови в об'єкті. Якщо сервер не бажає надавати цю інформацію клієнту, замість цього може використовуватися код статусу 404 (не знайдено). " Я не бачу там наголосів ("ДОЛЖЕН / НЕ" - це ключові слова RFC 2119, а не наголос); це ваша ідея, що означає "заборонено", а не RFC.
Пісквор вийшов з будівлі

10
Мені подобається ця відповідь, але все ж бачу одну невелику проблему. Відповідно до специфікації , коли повертається 403 , "запит НЕ повинен повторюватися". Однак повернення 409 "дозволено лише в тих випадках, коли очікується, що користувач зможе вирішити конфлікт і повторно подати запит". Що стосується дубліката, я думаю, що 403 тоді є більш підходящим, оскільки ви не можете реально вирішити конфлікт (за винятком випадків, видаливши попередній екземпляр ресурсу).
pablobm

2
Для самого повідомлення про помилку ви повинні змінити фразу причини, тому надсилання заголовка HTTP/1.0 403 Form validation errors- це найпростіший шлях.
aleemb

6
ІМО, 422 "Недоступна організація" має набагато більше сенсу. Моє міркування полягає в тому, що сервер не відмовляється виконувати запит, це те, що сервер не може виконати запит.
tybro0103

225

Я рекомендую код статусу 422, "Недоступний об'єкт" .

11.2. 422 Недоступна особа

Код стану 422 (Unprocessable Entity) означає, що сервер розуміє тип вмісту об'єкта запиту (отже, код статусу 415 (непідтримуваний тип медіа) неприйнятний), і синтаксис об'єкта запиту є правильним (таким чином, 400 (поганий запит) ) код статусу невідповідний), але не вдалося обробити містяться інструкцій. Наприклад, ця умова помилки може виникнути, якщо орган запиту XML містить добре сформовані (тобто синтаксично правильні), але семантично помилкові інструкції XML.


11
Звичайно, це код статусу HTTP, див. Iana.org/assignments/http-status-codes . Існує більше кодів статусу, ніж визначених у RFC 2616.
Julian

7
WebDAV - розширення HTTP . "Розширення HTTP для веб-розподілених авторизацій та версій (WebDAV)" Отже, код статусу 422 - це не код статусу http, а код статусу виходів http.
Деймон

16
Діамоне, це не має сенсу. HTTP визначає, як визначити нові коди, і саме це робить WebDAV. Реєстрація коду статусу є причиною.
Джуліян Решке

14
FYI - RFC опис 422: 11.2. 422 Недоступний об'єкт Код статусу 422 (Unprocessable Entity) означає, що сервер розуміє тип вмісту об'єкта запиту (отже, код статусу 415 (Непідтримуваний тип медіа) неприйнятний), і синтаксис об'єкта запиту є правильним (таким чином, 400 (Неправильний запит) код статусу невідповідний), але не вдалося обробити вміщені інструкції. Наприклад, ця умова помилки може виникнути, якщо орган запиту XML містить добре сформовані (тобто синтаксично правильні), але семантично помилкові інструкції XML.
Стів Каллестад

6
І теми не закінчуються. Їх потрібно продовжувати жити, або результати пошуку в Google Google починають ставати неточними.
Джеймс Біллінгем

81

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

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


2
Як щодо помилок, що виникають внаслідок взаємодії між арґугами. Тобто, arg1це дійсно і arg2є дійсним, але поєднання двох із надісланими конкретними значеннями недійсне.
Йона

1
Я б не думав про це; просто виберіть той, який, як видається, є власником відносин.
sethcall

або навіть просто помилка обох аргументів. Як користувач, я думаю, я хотів би побачити помилку в кожному з конфліктуючих полів, я думаю.
притупляється

Приємно !. явне краще, ніж неявне
bhathiya-

46

200

Фу ... (309, 400, 403, 409, 415, 422) ... багато відповідей, намагаючись вгадати, аргументувати та стандартизувати, що є найкращим кодом повернення для успішного запиту HTTP, але невдалого виклику REST .

Це неправильно змішувати HTTP коди статусу і коди стану спокою.

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

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

Наприклад, повернення "404 не знайдено" під час дзвінка / користувачів / плутає, бо це може означати:

  • URI неправильний (HTTP)
  • Користувачів не знайдено (REST)

"403 заборонено / заборонено доступ" може означати:

  • Потрібен спеціальний дозвіл. Браузери можуть це впоратися, запитуючи користувача / пароль. (HTTP)
  • Неправильні дозволи доступу, налаштовані на сервері. (HTTP)
  • Вам потрібно пройти автентифікацію (REST)

І список може продовжуватися "500 помилками сервера" (помилка, кинута HTTP Apache / Nginx або помилка обмеження бізнесу в REST) ​​або іншими помилками HTTP тощо ...

З коду важко зрозуміти, що було причиною відмови, помилкою HTTP (транспорту) або REST (логічним) збоєм.

Якщо запит HTTP фізично був виконаний успішно, він завжди повинен повертати 200 код, незалежно від того, знайдено чи ні запис. Оскільки ресурс URI знайдений та обробляється сервером HTTP. Так, він може повернути порожній набір. Чи можливо отримати порожню веб-сторінку з результатом 200 як HTTP, правда?

Замість цього ви можете повернути 200 HTTP-код з деякими параметрами:

  • Об'єкт "помилка" в результаті JSON, якщо щось піде не так
  • Порожній масив / об’єкт JSON, якщо запису не знайдено
  • Прапор результату / успіху у поєднанні з попередніми параметрами для кращого керування.

Також деякі інтернет-провайдери можуть перехопити ваші запити та повернути вам 404 HTTP-код. Це не означає, що ваші дані не знайдені, але на транспортному рівні щось не так.

З Вікі :

У липні 2004 року британський провайдер телекомунікаційних послуг BT Group розгорнув систему блокування вмісту Cleanfeed, яка повертає помилку 404 у будь-який запит на вміст, визначений Фондом Інтернет-годин, як потенційно незаконний. Інші провайдери повертають 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. API REST - це ваш, визначте ваші коди статусу.


3
Насправді, використання кодів HTTP-статусу для REST ще більше заплутує в дорозі: 1) ви бачите 4xx у панелі інструментів свого розробника, і ви не можете сказати, просто поглянувши на це, повернув чи сервер якесь розумне значення чи не обробив ваш запит взагалі. а потім 2) усі ваші обробники помилок / винятків / лову повинні перевірити, який сервер повернувся як відповідь (здебільшого вони цього не роблять, оскільки вам доведеться робити це під час кожного дзвінка служби) та багато разів 3) ви отримуєте однаковий корисний навантаження ( тип) на шляху до успіху та помилки, що веде до складного / дублюваного коду ... Дійсно заплутано.
szczepanpp

9
Ця відповідь плутає оригінальну семантику протоколу HTTP порівняно з тим, як REST через HTTP як архітектурний стиль переназначає HTTP для реалізації API веб-служб. Як архітектурний стиль, REST - це не стандарт, якого слід суворо дотримуватися, це запропонований підхід. Використання відповіді 200 для помилки перевірки не є правильним чи неправильним, однак, це заплутує ваших клієнтів, щоб відповісти, що запит вдався, але насправді не вдався через помилку перевірки, важлива деталь, яка затьмарюється в тілі відповіді, семантика якої клієнт повинен розібратися, щоб зрозуміти.
Кевін Гук

5
@Marcodor, якщо виклик API не вдається, але ви повернете 200, що свідчить про успіх, як це гарна ідея? це незрозуміло і заплутано для споживачів вашого API.
Кевін Гук

3
Виправте з багатьох причин, а не лише розділення помилок HTTP та REST. Перевірка REST часто вимагає більше нюансів. Наприклад, запис, прийнятий, але позначений як дублікат проти відхиленого за унікальне порушення індексу. Ви також хочете послідовної моделі повернення. Метод .NET BadRequest()має власну модель повернення, яка буде відрізнятися від звичайної моделі повернення. Це кошмар для розбору. @KevinHooke, повертаючи HTTP 200 за помилку перевірки REST - це як сказати: "Я отримав ваше повідомлення, відповідь - ні, і ось чому". Повертаючись до HTTP 400, каже: "Я не знаю, про що ви говорите".
Ніл Ласлетт

5
аргумент "тому, що Google це робить, це має бути правильно", для мене це божевільно ... це нормально, щоб оскаржити щось, що Google реалізував дітей. Повернення HTTP 200 для невдалого виклику спокою заплутає абонента API, він повинен бути 4xx, і в нього може бути досить JSON / XML в тілі ... дозволяє зупинити безумство разом.
Джеріл Кук

43

Дублікат у базі даних повинен бути 409 CONFLICT.

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

Я даю довше пояснення кодів 4xx тут .


6

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

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

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

Іншими словами, запит хороший, але оскільки ресурс вже існує, сервер не потребує подальшої обробки.


6
Як я зрозумів, 304 призначений для GET-операцій, щоб допомогти кешувати.
Сінестетик

6

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.