Відповідь 400 проти 422 на POST даних


355

Я намагаюся розібратися, який правильний код статусу для повернення в різних сценаріях за допомогою API "REST-like", над яким я працюю. Скажімо, у мене є кінцева точка, яка дозволяє здійснювати покупки POST'ing у форматі JSON. Це виглядає приблизно так:

{
    "account_number": 45645511,
    "upc": "00490000486",
    "price": 1.00,
    "tax": 0.08
}

Що я повинен повернути, якщо клієнт надсилає мені "sales_tax" (замість очікуваного "податку"). Наразі повертаю 400. Але я почав розпитувати себе з цього приводу. Чи повинен я справді повертати 422? Я маю на увазі, це JSON (який підтримується) і він дійсний JSON, він просто не містить усіх необхідних полів.


Відповіді:


419

400 поганий запит тепер, здається, є найкращим кодом статусу HTTP / 1.1 для вашого випадку використання.

На момент Вашого запитання (і моєї оригінальної відповіді) RFC 7231 не була річчю; в цей момент я заперечив, 400 Bad Requestтому що RFC 2616 сказав (з моїм наголосом):

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

і запит, який ви описуєте, є синтаксично дійсним JSON, укладеним у синтаксично допустимий HTTP, і, таким чином, сервер не має проблем із синтаксисом запиту.

Однак, як вказував Лі Саферіт у коментарях , RFC 7231, який застаріло RFC 2616, не включає це обмеження :

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


Однак перед цим переформулюванням (або якщо ви хочете посперечатися з приводу того, що RFC 7231 є лише запропонованим стандартом зараз), 422 Unprocessable Entityне здається неправильним кодом статусу HTTP для вашого випадку використання, оскільки, як свідчить вступ до RFC 4918:

Хоча коди статусу, надані HTTP / 1.1, є достатніми для опису більшості умов помилок, з якими стикаються методи WebDAV, є деякі помилки, які не належать акуратно до існуючих категорій. Ця специфікація визначає додаткові коди статусу, розроблені для методів WebDAV (Розділ 11)

І опис422 говорить:

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

(Зверніть увагу на посилання на синтаксис; я підозрюю, що 7231 частково застаріло 4918 також)

Це звучить точно як ваша ситуація, але на всякий випадок, коли виникли сумніви, він продовжує говорити:

Наприклад, ця умова помилки може виникнути, якщо орган запиту XML містить добре сформовані (тобто синтаксично правильні), але семантично помилкові інструкції XML.

(Замініть "XML" на "JSON", і я думаю, що ми можемо погодитися, що це ваша ситуація)

Тепер деякі заперечують, що RFC 4918 йдеться про "розширення HTTP для веб-розподілених авторизацій та версій (WebDAV)" і що ви (імовірно) нічого не робите з WebDAV, тому не повинні використовувати речі з нього.

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

Крім того, RFC 4918, розділ 21.4, посилається на реєстр кодів статусу протоколу передачі гіпертексту IANA (HTTP) , де їх можна знайти 422.

Я пропоную, щоб клієнт або сервер HTTP цілком доцільно використовувати будь-який код статусу з цього реєстру, якщо вони роблять це правильно.


Але що стосується HTTP / 1.1, RFC 7231 має тягу, тому просто використовуйте 400 Bad Request!


5
Ваша відповідь (422) для мене має сенс. Це також те, що Rails ( respo_with ) використовує, коли ресурс не вдалося обробити через помилки перевірки.
Тайлер Рік

11
Зверніть увагу на використання 422 у специфікаціях, що не належать до WebDAV, тут: tools.ietf.org/html/rfc5789#section-2.2
Андрій

4
Як і оновлення, RFC 7231 має інший опис коду відповіді 400, який змінює семантику.
Лі Саферит

5
Мої вибачення - я оновив цю відповідь, щоб відобразити зміну RFC і втратив ясність; Я спробую зробити рефактор. Це майже напевно безпечно використовувати 422, але сьогодні ви повинні використовувати 400.
Крістіан Скло

2
Я все ще думаю, що специфікація може бути набагато зрозумілішою. Наведені приклади - це явні випадки, коли клієнт робить щось не так. Ситуація з ОП також належить до цієї категорії. Однак є випадки типу "я розумію, про що ви просите, але я відмовляюся це робити, тому що є якесь ділове правило проти цього" - це не так однозначно. Це не зовсім вина клієнта, тому 403 може фактично застосовуватися за тією ж специфікацією: "Однак запит може бути заборонено з причин, не пов'язаних з обліковими даними". Я вважаю за краще мати окремі коди для матеріалів, що стосуються дозволу, але "це неможливо зробити".
Торарін

37

400 Неправильний запит - це правильний код статусу HTTP для вашого випадку використання. Код визначається HTTP / 0.9-1.1 RFC.

Сервер не міг зрозуміти запит через неправильний синтаксис. Клієнт НЕ повинен повторювати запит без змін.

http://tools.ietf.org/html/rfc2616#section-10.4.1

422 Недоступна сутність визначається RFC 4918 - WebDav. Зауважте, що незначна різниця порівняно з 400, див. Цитований текст нижче.

Ця умова помилки може виникнути, якщо тіло запиту XML містить добре сформовані (тобто синтаксично правильні), але семантично помилкові інструкції XML.

Для збереження єдиного інтерфейсу слід використовувати 422 лише у випадку відповідей XML, а також слід підтримувати всі коди статусу, визначені розширенням Webdav, а не лише 422.

http://tools.ietf.org/html/rfc4918#page-78

Дивіться також публікацію Марка Ноттінгема про коди статусу:

помилка намагатися скласти карту кожної частини програми «глибоко» в коди статусу HTTP; у більшості випадків рівень зернистості, до якого ви хочете прагнути, набагато грубіший. Коли ви сумніваєтесь, нормально використовувати загальні коди статусу 200 ОК, 400 Поганий запит та 500 Помилка внутрішньої служби, коли немає кращого пристосування .

Як думати про коди статусу HTTP


4
Код 422 є частиною реєстру IANA iana.org/assignments/http-status-codes/http-status-codes.xhtml, тому будь-який ІМХО не має сенсу. У будь-якому випадку Facebook і Twitter REST API винаходять власні коди та не використовують стандарти RFC / IANA. Так ви можете зробити.
gavenkoa

15
У розділі 11 конкретно зазначено, що вони додаються до всієї специфікації, а не лише до специфікації WebDav:The following status codes are added to those defined in HTTP/1.1 [RFC2616].
Стів Таубер

8
Тільки тому, що код описаний як частина специфікації WebDAV, це не означає, що це WebDAV! Коди статусу повинні бути загальними.
добре

33

Щоб відобразити статус станом на 2015 рік:

Поведінкові і 400, і 422 коди відповідей будуть оброблятися однаково клієнтами та посередниками, тому це фактично не робить конкретної різниці, яку ви використовуєте.

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

  • Специфікація HTTPbis роз'яснює намір 400 не лише для синтаксичних помилок. Ширше словосполучення "вказує на те, що сервер не може або не обробляє запит через те, що сприймається як помилка клієнта".
  • 422 конкретно є розширенням WebDAV і не посилається на RFC 2616 або новішу специфікацію HTTPbis .

У контексті HTTPbis - це перегляд специфікації HTTP / 1.1, яка намагається уточнити області, де незрозуміло чи непослідовно. Після досягнення затвердженого статусу він замінить RFC2616.


4
Чи не може 403 Заборонений також використовуватись у цьому контексті? Цитата: Код стану 403 (Заборонено) вказує на те, що сервер зрозумів запит, але відмовляється його авторизувати ... Якщо в запиті були надані облікові дані автентифікації, сервер вважає їх недостатніми для надання доступу .... Однак запит може бути бути забороненим з причин, не пов'язаних з обліковими даними. Таким чином, схоже, що 403 можна використовувати для відхилення запитів поза аутентифікацією.
garbagecollector

1
@garbagecollector зауважте, що "відхилено з причин, що не входять до облікових даних "! = "відхилено з причин, що не відповідають аутентифікації ". Існує маса способів аутентифікувати когось, не використовуючи конкретні дані.
Кнетик

@garbagecollector ні, облікові дані означають автентифікацію ("хто ти"), що було б 401 при відмові. Авторизація ("що ви можете зробити") буде 403 після відмови. Повне пояснення тут: stackoverflow.com/a/6937030/137948 Не застосовується і до ситуації "відсутніх полів" ОП, оскільки помилка була б однаковою незалежно від того, хто користувач намагався її. Я погоджуюся, що 400 - це правильна відповідь.
Буде Шеппард

27

Тематичний приклад: API GitHub

https://developer.github.com/v3/#client-errors

Можливо, копіювання з відомих API - це мудра ідея:

Існує три можливі типи помилок клієнта при викликах API, які отримують органи запиту:

Відправлення недійсного JSON призведе до відповіді на 400 запитів.

HTTP/1.1 400 Bad Request
Content-Length: 35

{"message":"Problems parsing JSON"}

Надсилання неправильного типу значень JSON призведе до відповіді 400 Поганий запит.

HTTP/1.1 400 Bad Request
Content-Length: 40

{"message":"Body should be a JSON object"}

Відправлення недійсних полів призведе до 422 відповіді не оброблюваної особи.

HTTP/1.1 422 Unprocessable Entity
Content-Length: 149

{
  "message": "Validation Failed",
  "errors": [
    {
      "resource": "Issue",
      "field": "title",
      "code": "missing_field"
    }
  ]
}

Я думаю, що це правильна і зрозуміла відповідь.
LEMUEL ADANE

1
Неможливо подати більше. Хотілося б, щоб більш схвалені відповіді стосувалися саме цієї. Технічні характеристики (RFC, IANA) епічно не дали чітких визначень та відмінностей між ними. Тож відповідь зводиться до найкращих практик, і GitHub дає нам це.
Олексій Клаус

15

Правильної відповіді немає, оскільки це залежить від того, яке визначення "синтаксису" відповідає вашому запиту. Найголовніше, що ви:

  1. Використовуйте коди (і) відповідей послідовно
  2. Включіть якомога більше додаткової інформації до органу відповідей, щоб допомогти розробнику, використовуючи свій API, розібратися, що відбувається. =

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

У цьому конкретному прикладі питання ОП стосується запиту JSON, який містить інший ключ, ніж очікувалося. Тепер отримане ім'я ключа дуже схоже, з точки зору природної мови, на очікуваний ключ, але він, суворо, відрізняється, а отже, машина (як правило) не визнається машиною як рівнозначна.

Як я вже говорив вище, вирішальним фактором є те, що мається на увазі синтаксисом . Якщо запит було надіслано з типом вмісту application/json, то так, запит є синтаксично дійсним, оскільки він є синтаксисом JSON, але не є семантично дійсним, оскільки не відповідає тому, що очікувалося. (припускаючи чітке визначення того, що робить запит семантично дійсним чи ні).

Якщо, з іншого боку, запит було надіслано з більш конкретним спеціальним типом вмісту, таким application/vnd.mycorp.mydatatype+json, як , можливо, вказується саме те, які поля очікуються, то я б сказав, що запит може бути синтаксично недійсним, отже, відповідь 400.

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


Дуже занижена відповідь - дякую за добре сформульоване пояснення.
puiu

Саме мої думки з цього приводу! Я виходжу з тла XML SOAP і концепція схеми щойно потрапила мені в кров, а документи JSON радше не оголошують їх схеми. Для мене це, чи "сервер" розуміє запит, чи ні. Якщо сервер не знає, що таке "sales_tax", то це просто 400: "Я поняття не маю, що ви мені надіслали, але точно не те, що я хочу".
Олександр Стельмацонек

4

422 Пояснений суб’єкт господарювання, який не переробляється Оновлено: 6 березня 2017 року

Що таке 422 об'єкт без обробки?

Код статусу 422 виникає, коли запит добре сформований, однак через смислові помилки його неможливо обробити. Цей HTTP-статус був запроваджений у RFC 4918 і більш конкретно орієнтований на розширення HTTP для Веб-розподіленого авторизації та версій (WebDAV).

Існує певна суперечка щодо того, чи варто розробникам повертати клієнтам помилку 400 проти 422 (докладніше про відмінності обох статусів нижче). Однак у більшості випадків погоджується, що статус 422 повинен бути повернутий лише у тому випадку, якщо ви підтримуєте можливості WebDAV.

Означення слова за словом коду статусу 422, взятого з розділу 11.2 в RFC 4918, можна прочитати нижче.

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

Визначення продовжує говорити:

Наприклад, ця умова помилки може виникнути, якщо орган запиту XML містить добре сформовані (тобто синтаксично правильні), але семантично помилкові інструкції XML.

400 проти 422 кодів статусу

Помилки помилок запиту використовують код стану 400 і його слід повернути клієнтові, якщо синтаксис запиту неправильно сформований, містить недійсне обрамлення повідомлення запиту або обманливу маршрутизацію запиту. Цей код статусу може виглядати досить схожим на статус 422 не оброблюваної сутності, однак, одна невелика інформація, яка їх відрізняє, - це той факт, що синтаксис об'єкта запиту про помилку 422 є правильним, тоді як синтаксис запиту, який генерує 400 помилка невірна.

Використання статусу 422 має бути зарезервовано лише для дуже конкретних випадків використання. У більшості інших випадків, коли помилка клієнта сталася через неправильно сформований синтаксис, слід використовувати статус 400 поганих запитів.

https://www.keycdn.com/support/422-unprocessable-entity/


1

Ваш випадок: HTTP 400 це правильний код статусу для вашої справи з точки зору REST як його синтаксично неправильний для надсилання sales_taxзамість цього tax, хоча це дійсний JSON. Зазвичай це виконується більшістю фреймворків на стороні сервера при зіставленні JSON об'єктам. Однак є деякі реалізації REST, які ігнорують нове keyв об'єкті JSON. У цьому випадку спеціальна content-typeспецифікація для прийняття лише дійсних полів може бути застосована стороною сервера.

Ідеальний сценарій для 422:

В ідеальному світі 422 є кращим і загальноприйнятним для надсилання як відповіді, якщо сервер розуміє тип вмісту об'єкта запиту і синтаксис об'єкта запиту є правильним, але не зміг обробити дані, оскільки його семантично помилковий.

Ситуація від 400 до 422:

Пам'ятайте, що код відповіді 422 - це розширений код статусу HTTP (WebDAV). Є ще деякі клієнти HTTP / передній бібліотеки, які не готові обробляти 422. Для них це так просто, як "HTTP 422 - це неправильно, оскільки це не HTTP" . З точки зору обслуговування, 400 не зовсім конкретні.

У архітектурі підприємства послуги розміщуються здебільшого на рівнях обслуговування, таких як SOA, IDM тощо. Вони, як правило, обслуговують декілька клієнтів, починаючи від дуже старого рідного клієнта до найновіших клієнтів HTTP. Якщо хтось із клієнтів не обробляє HTTP 422, можна запропонувати клієнту оновити або змінити ваш код відповіді на HTTP 400 для всіх. На мій досвід, це дуже рідко в ці дні, але все ж можлива. Отже, перш ніж визначитися з кодами відповідей HTTP, завжди потрібно ретельно вивчити вашу архітектуру.

Для обробки такої ситуації, сервісні шари зазвичай використовують versioningабо встановлюють configurationпрапор для суворих клієнтів відповідності HTTP для надсилання 400, а для решти 422 - відправлення 422. Таким чином, вони надають підтримку сумісності для існуючих споживачів, але одночасно забезпечують можливість нових клієнтів споживати HTTP 422.


Останнє оновлення до RFC7321 говорить:

The 400 (Bad Request) status code indicates that the server cannot or
   will not process the request due to something that is perceived to be
   a client error (e.g., malformed request syntax, invalid request
   message framing, or deceptive request routing).

Це підтверджує, що сервери можуть надсилати HTTP 400 за недійсний запит. 400 більше не посилається тільки на синтаксичну помилку , проте 422 все ще є справжньою відповіддю за умови, що клієнти можуть це впоратися.


1

По-перше, це дуже гарне питання.

400 Поганий запит - коли у запиті відсутня важлива інформація

наприклад, заголовок авторизації або заголовок типу вмісту. Що абсолютно необхідне серверу для розуміння запиту. Це може відрізнятися від сервера до сервера.

422 Недоступний об'єкт - коли тіло запиту неможливо проаналізувати.

Це менш серйозно, ніж 400. Запит дійшов до сервера. Сервер підтвердив, що запит отримав основне право. Але інформацію в тілі запиту неможливо проаналізувати або зрозуміти.

наприклад, Content-Type: application/xmlколи органом запиту є JSON.

Ось стаття з переліком кодів стану та їх використання в API REST. https://metamug.com/article/status-codes-for-rest-api.php


5
422 означає, що синтаксис дійсний, але вміст - ні. Надіслати JSON там, де очікується XML, означає, що синтаксис невірний, тож 400 - це правильна відповідь у цьому випадку.
Дірк

1
Дірк сказав, що 422 означає синтаксично дійсний запит (може бути проаналізований і зрозумілий), але семантично недійсний
Яцек Обарамський

400: коли запит не може бути оброблений через неправильний синтаксис (наприклад, помилка розбору); 422: коли запит не може бути оброблений через недійсні дані (наприклад, помилка перевірки).
Кітаноторі

Ваш приклад для 422 не вірно, тому що, надсилаючи json з додатком / xml тип медіа, тіло автоматично є синтаксично неправильним, а відповідь має бути 400.
manemarron

-15

Ви насправді повинні повернути "200 ОК", а в орган відповіді включити повідомлення про те, що сталося з опублікованими даними. Тоді саме від вашої заявки потрібно зрозуміти повідомлення.

Вся справа в тому, що коди статусу HTTP саме такі - коди статусу HTTP. І вони повинні мати значення лише на транспортному шарі, а не на рівні програми. Рівень програми насправді ніколи навіть не повинен знати, що використовується HTTP. Якщо ви переключили свій транспортний шар з HTTP на Homing Pigeons, це ніяк не повинно впливати на ваш додаток.

Дозвольте навести вам невіртуальний приклад. Скажімо, ви закохаєтесь у дівчину, і вона любить вас назад, але її родина переїжджає до зовсім іншої країни. Вона дає вам свою нову адресу равликової пошти. Природно, ви вирішили надіслати їй любовний лист. Тож ви пишете свій лист, кладете його в конверт, пишете на його конверті її адресу, ставите на ній штамп і відправляєте. Тепер розглянемо ці сценарії

  1. Ви забули написати назву вулиці. Ви отримаєте назад незакритий лист із написом на ньому повідомлення про те, що адреса неправильна. Ви накрутили запит, і приймаюче поштове відділення не в змозі впоратися з ним. Це еквівалент отримання "400 поганих запитів".
  2. Тож ви фіксуєте адресу і відправляєте лист ще раз. Але через якусь невдачу ви повністю помилково написали назву вулиці. Ви знову отримаєте лист із повідомленням, що адреси не існує. Це еквівалент отримання "404 не знайдено".
  3. Ви знову виправляєте адресу, і цього разу вам вдалося правильно записати адресу. Ваша дівчина отримує лист і пише вам назад. Це еквівалент отримання "200 ОК". Однак це не означає, що вам сподобається те, що вона написала у своєму листі. Це просто означає, що вона отримала ваше повідомлення і має відповідь для вас. Поки ви не відкриєте конверт і не прочитаєте її лист, ви не можете знати, чи вона вам дорого сумує, чи хоче розлучитися з вами.

Якщо коротко: повернення "200 ОК" не означає, що серверна програма має для вас добрі новини. Це означає лише, що в ньому є деякі новини.

PS: Код стану 422 має значення лише в контексті WebDAV. Якщо ви не працюєте з WebDAV, тоді 422 має точно таке ж стандартне значення, як і будь-який інший нестандартний код = якого немає.

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