Чи повинен я повернути статус HTTP 400 (неправильний запит), якщо параметр синтаксично правильний, але порушує правило бізнесу?


56

Скажіть, що у мене є кінцева точка REST, яка приймає ціле число в якості параметра:

/makeWaffles?numberOfWaffles=3

У цьому випадку я хочу, щоб число було позитивним, оскільки я не можу зробити негативну кількість вафель (а запитувати 0 вафлі - це марна трата часу). Тому я хочу відхилити будь-який запит, який не містить додатного цілого числа. Я також хочу відхилити запит, який перевищує деяке максимальне ціле число (скажімо поки що це MAX_INTEGER).

У разі, якщо хтось запитує непозитивну кількість вафлі, я повинен повернути статус HTTP 400 (поганий запит)? Моя початкова думка - так: це неправдиве число для заповнення запиту. Однак, RFC не згадує бізнес-правил як причину, щоб кинути їх:

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

Правило бізнесу не підпадає під жоден із цих трьох прикладів. Це синтаксично правильно, правильно оформлено, і це не обманний запит.

Тож чи варто повернути стан HTTP 400 (неправильний запит), якщо параметр є синтаксично правильним, але порушує правило бізнесу? Або є більш підходящий статус для повернення?



Відповіді:


38

Це велике запитання і все ще дуже актуальне з огляду на історичний контекст (і, здавалося б, суперечливі визначення) HTTP-кодів повернення. Навіть серед відповідей на це питання є суперечливі визначення. Це можна з’ясувати, рухаючись хронологічно.

RFC 2616 (червень 1999 р.)

10.4.1 400 Поганий запит

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

Станом на цей RFC цей код статусу спеціально застосовується лише до синтаксично недійсних запитів. У кодах статусу був розрив для семантичної перевірки. Таким чином, коли RFC 4918 прийшов навколо, народився новий код.

RFC 4918 (червень 2007 р.)

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

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

422 Недоступна сутність створена для заповнення проміжку семантичної перевірки в оригінальній специфікації кодів статусу 4xx. Однак у 2014 році з'явився ще один відповідний RFC, який узагальнив 400, щоб вони більше не були специфічними для синтаксису .

RFC 7231 (червень 2014 року, явно застаріло RFC 2616)

6.5.1. 400 Поганий запит

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

Зауважимо, що в описі 422 йдеться про те, що причина 400 є невідповідною, оскільки 400 (як у RFC 2616) повинен бути повернутий лише для синтаксису поганого запиту. Однак, як і для RFC 7231, суворе визначення синтаксичної помилки більше не застосовується до 400 .

Назад до питання: Хоча 422 є технічно більш конкретним, враховуючи цей контекст, я можу побачити, як 400 або 422 використовуються для семантичної перевірки параметрів API. Я не вагаюся використовувати 422 у власних API, тому що визначення 422 технічно застаріло на даний момент (хоча я не знаю, чи це офіційно визнано де-небудь). Стаття, на яку посилається у відповіді Фран, що заохочує використання 422, була написана в 2012 році, за два роки до того, як RFC 7231 уточнив HTTP 400. Просто не забудьте стандартизувати те чи інше.


42

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

від IETF

422 Unprocessable Entity (WebDAV; RFC 4918) Запит був добре сформований, але його не вдалося виконати через семантичні помилки

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


5
Я чув, як це описано як "400 означає поганий синтаксис, 422 - погана семантика".
cbojar

33
Всі коди x00 - це загальні коди "ловити всі". 400 не є недоречним , а лише менш конкретним .
Джек

1
Хороша відповідь, але відповідь, яку дав @GoFree, має для мене більше сенсу.
Евертон

2
Є справді вагомий випадок повернення кодів, про який знають усі. Абсолютно всім потрібно буде шукати 422, і я буду вважати, що більшість все ще не знатиме, що з цього зробити.
sylvanaar

8

Так, вхід, який не відповідає передбачуваному контракту кінцевої точки, "є щось, що сприймається як помилка клієнта", і має повертати 400.

Винятки з цього є, якщо ділове правило пов'язане з безпекою (тоді 401 Unauthorizedабо 403 Forbiddenбуло б краще). Крім того, якщо надсилання 400 витікає інформацію про існування чогось, і тоді 404 Not Foundможе бути більш підходящим.


8

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

Уявіть, що відбувається апокаліпсис, і вам доведеться перейти з протоколу HTTP на використання Pigeons. Голуби не мають жодних зворотних кодів, тому вам потрібно буде змінити рівень свого бізнесу, щоб пристосувати його. Але ваш бізнес насправді ніяк не змінився, тому вам не потрібно змінювати рівень бізнесу. Він показує тісний зв'язок між цими двома шарами (транспортом та бізнесом).

Повернення до питання: Що потрібно зробити, це повернути "200 ОК" з тілом, що описує те, що сталося з запитом. У специфікації чітко сказано так:

https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1 .

200 ОК

Запит вдався. Інформація , яка повертається з відповіддю залежить від методу , який використовується в запиті , наприклад ,

POST об'єкт, що описує або містить результат дії;

Чи вдався ваш запит HTTP? Так, веб-сервер знає, що робити з цим запитом (наприклад, передати його на серверну частину вашої програми). Потім веб-сервер передає цей запит до серверної частини вашої програми, яка приймає дані POSTed, обробляє їх (перевіряє їх у вашому випадку) і повертає звичайну відповідь (в тілі відповіді HTTP) клієнтській частині вашої програми . Ця відповідь серверної частини програми може бути або "Чудово, дані, які ви мені надіслали, є дійсними", або "Вибачте, дані, які ви надіслали, недійсні". І саме від вашої клієнтської частини програми потрібно зрозуміти, що означає відповідь.

PS: "400 поганий запит" означає, що веб-сервер не зрозумів, що ви хочете від нього. Це означає, що ваша серверна частина вашої програми навіть не отримала запит. Або, принаймні, так це означає :-)

EDIT : Я щойно зрозумів, що ви робите GET запит, а не POST. Це погана ідея, оскільки GET не повинен змінювати стан програми. GET повинен просто отримати дані з сервера. Але у своєму запиті ви фактично змінюєте стан програми, тому ви дійсно повинні використовувати POST.


1
Так, повернення 404 у цьому випадку прекрасне. Я не кажу, що сервер завжди повинен надсилати 200 ОК із поясненням у тілі.
GoFree

Краще пояснення я бачив досі. У мене цей же питання , і здається , що все слово думає Differente від мене , і ви @GoFree
Ewerton

@GoFree Це дійсно гарна відповідь на переосмислення дизайну API. Але чи не так, що ми використовуємо HTTP та його код відповіді як важливу частину рівня бізнес-правил, коли ми використовуємо API REST?
Томас Лаурія

1
@Thomas Lauria Я ще не бачив належної реалізації RESTFUL API. Однак REST API - це модна мова сьогодні, тому кожній компанії доводиться користуватися ним (словом, а не технологією), не розуміючи фактично поняття, що стоїть за ним. Так що так, його повсюдно використовують неправильно. Що зазвичай створюють програмісти, це не API REST, а HTTP API або API OVER HTTP. Насправді однією з небагатьох хороших RESTFUL реалізацій є сам HTTP :)
GoFree

1
Використання 200-ОК особливо логічно, якщо програма містить поле "помилка" в тілі відповідей для опису будь-яких помилок на рівні бізнесу, таких як вхідне значення занадто високе або занадто низьке або відсутнє, товар недоступний тощо.
Roland

-3

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


5
409 означає "стан, в який ви намагаєтеся вкласти це, конфліктує зі станом, який намагається вкласти інший клієнт", це для блокування паралельних записів (наприклад, використовуючи ETags)
Джек
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.