Jaka jest odpowiednia odpowiedź kodu stanu HTTP na ogólne nieudane żądanie (nie jest to błąd)?


109

Tworzę RESTful API, które będzie przetwarzać szereg interakcji użytkownika, w tym składanie zamówień przy użyciu zapisanych kart kredytowych.

W przypadku pomyślnego zamówienia zwracam 200 OK, aw przypadku, gdy żądanie zamówienia jest źle sformułowane lub nieprawidłowe, zwracam 400 złych żądań. Ale co mam zwrócić, jeśli podczas realizacji zamówienia wystąpi problem?

  1. Zlecenie klienta POSTS do serwera dla zasobu użytkownika. Jeśli użytkownik nie istnieje, zwracany jest błąd 404 Not Found.
  2. Format zamówienia i informacje są sprawdzane. Jeśli nie jest poprawne, zwracanych jest 400 złych żądań.
  3. Zamówienie jest realizowane. Jeśli zamówienie się powiedzie, dla zamówienia zwracany jest 201 Utworzony. W przypadku napotkania nieoczekiwanego błędu zwracany jest błąd 500 serwera.

Ostatnim krokiem jest problem - co mam zwrócić, jeśli zamówienie nie zostało zrealizowane z innego powodu? Możliwe scenariusze mogą obejmować:

  • Produkt wyprzedany
  • Osiągnięto maksymalny limit zamówień użytkownika
  • Niepowodzenie transakcji kartą kredytową (niewystarczające środki itp.)

Wydaje się, że to nie byłoby odpowiednie dla 400 lub 500. Jeśli cokolwiek mógłbym zobaczyć to jako 400, jeśli nie ma lepszego kodu - żądanie było nieprawidłowe zgodnie z regułami biznesowymi. To po prostu nie wydaje się dokładne.

Edycja: znalazłem również tę istniejącą dyskusję na ten sam temat. Wszystkie odpowiedzi wydają się wskazywać na używanie kodów stanu dla tego typu naruszeń, z pewną dyskusją między używaniem rozszerzenia 400, 409 lub 422.


8
Lubię "422 unprocessable entity" za błędy walidacji. Wykorzystaj to w powyższych przykładach, dołącz wiadomość do odpowiedzi z rzeczywistym problemem biznesowym „Produkt jest wyprzedany” i ewentualnie dodaj własne „kody”, jeśli klient musi programowo podejmować różne decyzje na podstawie odpowiedzi
house9

zanim przejdziesz do 422, zastanów się, czy obsługujesz funkcje WebDAV
Mbithy Mbithy

Odpowiedzi:


90

Powinieneś użyć 400 dla reguł biznesowych. Nie zwracaj 2xx, jeśli zamówienie nie zostało przyjęte. HTTP to protokół aplikacji, nigdy o tym nie zapominaj. Jeśli zwrócisz 2xx, klient może założyć, że zamówienie zostało przyjęte, niezależnie od jakichkolwiek informacji, które prześlesz w treści.


Z książki kucharskiej RESTful Web Services :

Jednym z częstych błędów popełnianych przez niektóre usługi sieciowe jest zwracanie kodu stanu, który odzwierciedla sukces (kody stanu od 200 do 206 i od 300 do 307), ale zawiera treść komunikatu opisującą stan błędu. Dzięki temu oprogramowanie obsługujące protokół HTTP nie będzie w stanie wykryć błędów. Na przykład pamięć podręczna zapisze ją jako pomyślną odpowiedź i przekaże ją kolejnym klientom, nawet jeśli klienci będą mogli wykonać udane żądanie.

Tobie pozostawiam wybór między 4xx a 5xx, ale powinieneś użyć kodu statusu błędu.


1
Czy masz jakieś przykłady lub odniesienia do tego podejścia w porównaniu z innym? Odpowiedzi zarówno twoje, jak i Widora mają sens, jedna z punktu widzenia HTTP jako protokołu aplikacji, a druga, ponieważ jest ściśle związana z celem transferu. Specyfikacja definiuje go jako „protokół poziomu aplikacji”, co jest trochę niejasne. Badając to, widziałem również perspektywy i przykłady w sieci.
Raelshark,

to jest takie prawdziwe.
Young Hyun Yoo

2
Czy masz na myśli: „Powinieneś używać 4xx dla reguł biznesowych”?
Yawar

28

Należy użyć 4xx dla błędu klienta, jeśli klient może zmodyfikować żądanie, aby obejść błąd. Użyj 5xx dla błędu serwera, którego klient nie może naprawdę obejść.

Produkt wyprzedany byłby błędem serwera. Klient nie może w jakiś sposób zmodyfikować żądania, aby obejść błąd. Możesz przejść na inny produkt, ale czy nie byłaby to nowa prośba?

Osiągnięcie maksymalnego limitu zamówień użytkownika jest również błędem serwera. Klient nie może nic zrobić, aby obejść ten błąd.

Niepowodzenie transakcji kartą kredytową byłoby błędem klienta. Klient może ponownie przesłać żądanie, podając inną metodę płatności lub numer karty kredytowej, aby obejść błąd.


6
Czy w przypadku osiągnięcia limitu zamówień klient nie powinien powiadomić o tym użytkownika i pozwolić mu odpowiednio zmienić żądanie? To wygląda na błąd 4xx. To samo dotyczy wyprzedanego produktu. Błędy 5xx są przeznaczone dla błędów, które są spowodowane awarią systemu w jakiś sposób, a nie dla działań, które są zabronione przez regułę biznesową.
carlin.scott

7
Zgadzam się z powyższym komentarzem. Błędy 5xx dotyczą sytuacji, w których występują problemy z serwerem. Błędy 4xx dla reguł biznesowych.
Merc

21

Typ błędu:

4×× Client Error

Kod błędu:

422 Unprocessable Entity

Serwer rozumie typ zawartości jednostki żądania (stąd kod statusu 415 nieobsługiwanego typu nośnika jest niewłaściwy), a składnia jednostki żądania jest poprawna (w związku z tym kod statusu 400 złego żądania jest nieodpowiedni), ale nie mógł przetworzyć zawartego instrukcje.

Na przykład ten warunek błędu może wystąpić, jeśli treść żądania XML zawiera poprawnie sformułowane (tj. Poprawne składniowo), ale semantycznie błędne instrukcje XML.

https://httpstatuses.com/422


16

Wiem, że to pytanie jest stare, ale dziś zadałem to samo. Jeśli mojemu użytkownikowi skończą się kredyty, jaki kod stanu powinien zwrócić mój REST API?

Mam skłonność do 402 Payment Required:

Według Wikipedii :

Zarezerwowane do użytku w przyszłości. Pierwotnym zamiarem było to, że ten kod może zostać użyty jako część jakiejś formy cyfrowej gotówki lub schematu mikropłatności, ale tak się nie stało, a ten kod zwykle nie jest używany. Interfejs Google Developers API używa tego stanu, jeśli określony programista przekroczył dzienny limit żądań.

I rzeczywiście robią :

PAYMENT_REQUIRED (402)

  • Osiągnięto dzienny limit budżetu ustawiony przez programistę.
  • Żądana operacja wymaga więcej zasobów niż pozwala na to przydział. Do zakończenia operacji wymagana jest płatność.
  • Żądana operacja wymaga jakiejś płatności od uwierzytelnionego użytkownika.

To najbardziej przemyślana i logiczna odpowiedź.
GTodorov

5

A co powiesz 424 Failed Dependency? Specyfikacja opisuje to jako:

Nie można wykonać metody na zasobie, ponieważ żądana akcja zależała od innej akcji i ta akcja nie powiodła się.

Ale jest też taka definicja :

Kod statusu 424 jest zdefiniowany w standardzie WebDAV i dotyczy przypadku, gdy klient musi zmienić to, co robi - serwer nie ma tutaj żadnego problemu.

Możesz powiedzieć klientowi (lub udawać), że masz wewnętrzne akcje, które mają stworzyć zamówienie i odliczyć saldo, i że jedna z tych czynności nie powiodła się, choć z całkowicie uzasadnionych powodów, i dlatego żądanie się nie powiodło.

Z tego, co widzę, „akcja” jest pojęciem dość szerokim i może być używane w różnych sytuacjach, w tym w przypadku niewystarczających zapasów, niewystarczających kredytów lub nocnej imprezy magazynowej.


Inną opcją może być 422 Unprocessable Entity:

Serwer rozumie typ zawartości jednostki żądania (stąd kod statusu 415 nieobsługiwanego typu nośnika jest niewłaściwy), a składnia jednostki żądania jest poprawna (w związku z tym kod statusu 400 złego żądania jest nieodpowiedni), ale nie mógł przetworzyć zawartego instrukcje.

Na przykład ten warunek błędu może wystąpić, jeśli treść żądania XML zawiera poprawnie sformułowane (tj. Poprawne składniowo), ale semantycznie błędne instrukcje XML.

Próba zażądania pozycji, której nie ma w magazynie lub gdy masz niewystarczający kredyt, może zostać uznana za błąd na poziomie semantycznym.

MozDev mówi, że oznacza to błąd po stronie klienta, w szczególności: klient nie powinien powtarzać tego żądania bez modyfikacji.

Loopback 4 używa 422, gdy sprawdzanie poprawności danych wejściowych nie powiedzie się.


Prawdopodobnie niewystarczające zapasy lub noc przyjęć w magazynie można uznać za stany tymczasowe, więc żądanie może zostać ponowione później. Na taką sytuację może wskazywać503 Service Unavailable

Serwer nie jest obecnie w stanie obsłużyć żądania z powodu tymczasowego przeciążenia lub zaplanowanej konserwacji, która prawdopodobnie zostanie złagodzona po pewnym opóźnieniu.

Serwer MOŻE wysłać pole nagłówka Retry-After, aby zasugerować klientowi odpowiednią ilość czasu na czekanie przed ponowną próbą żądania.


Żaden z nich nie dotyczy płatności. Idę z 402 z poprzedniej odpowiedzi!
GTodorov

2

Nie sądzę, by można było użyć 400 do wszystkich scenariuszy biznesowych. Może być używany do walidacji podstawowych danych wejściowych. Poza tym możemy mieć trudności z dopasowaniem innej logiki biznesowej do tego kodu błędu. Obsługiwane przez to błędy to głównie błędy czasu projektowania, które programista może napotkać podczas kodowania klienta.

Powiedzmy, że wszystkie parametry są poprawne i powiedzmy, że przekazujemy do żądania numer konta użytkownika.

Tak więc żądanie nie jest już złym żądaniem, serwer może je zaakceptować. Ale teraz odmawia wypełnienia wniosku na podstawie nowych dostępnych informacji, czyli - konto nie ma wystarczającego salda.

Sugerowałbym użycie 403 z odpowiednim komunikatem o błędzie w tych scenariuszach.

Innym możliwym kodem błędu może być konflikt 409. Ale jest to używane w scenariuszach, w których zasób jest w spójnym stanie.


-1

Idę z 406 Not Acceptable.

Oto lista 4xx:

const HTTP_BAD_REQUEST = 400;
const HTTP_UNAUTHORIZED = 401;
const HTTP_PAYMENT_REQUIRED = 402;
const HTTP_FORBIDDEN = 403;
const HTTP_NOT_FOUND = 404;
const HTTP_METHOD_NOT_ALLOWED = 405;
const HTTP_NOT_ACCEPTABLE = 406;
const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
const HTTP_REQUEST_TIMEOUT = 408;
const HTTP_CONFLICT = 409;
const HTTP_GONE = 410;
const HTTP_LENGTH_REQUIRED = 411;
const HTTP_PRECONDITION_FAILED = 412;
const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
const HTTP_REQUEST_URI_TOO_LONG = 414;
const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
const HTTP_EXPECTATION_FAILED = 417;
const HTTP_I_AM_A_TEAPOT = 418;                                               // RFC2324
const HTTP_MISDIRECTED_REQUEST = 421;                                         // RFC7540
const HTTP_UNPROCESSABLE_ENTITY = 422;                                        // RFC4918
const HTTP_LOCKED = 423;                                                      // RFC4918
const HTTP_FAILED_DEPENDENCY = 424;                                           // RFC4918
const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;   // RFC2817
const HTTP_UPGRADE_REQUIRED = 426;                                            // RFC2817
const HTTP_PRECONDITION_REQUIRED = 428;                                       // RFC6585
const HTTP_TOO_MANY_REQUESTS = 429;                                           // RFC6585

8
Chociaż sama nazwa kodu statusu 406 może wydawać się dokładna, należy mieć świadomość, że każdy kod statusu ma autorytatywny opis tekstowy. Opis kodu stanu 406 nie jest odpowiedni dla omawianego przypadku. Na przykład patrz httpstatuses.com/406 .
Zero3

1
@ Zero3 ma rację, ten kod oznacza, że ​​typ odpowiedzi jest niedopuszczalny, ponieważ istnieje niezgodność między nagłówkami akceptacji wysłanymi z klienta a typami nośników wysłanymi przez punkt końcowy, np. Application / json vs. text / plain
Gregor
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.