Błąd interfejsu API REST zwraca dobre praktyki [zamknięte]

623

Szukam wskazówek dotyczących dobrych praktyk, jeśli chodzi o zwracanie błędów z interfejsu API REST. Pracuję nad nowym interfejsem API, dzięki czemu mogę teraz obrać dowolny kierunek. Mój typ zawartości to XML, ale planuję w przyszłości obsługiwać JSON.

Teraz dodam kilka przypadków błędów, na przykład klient próbuje dodać nowy zasób, ale przekroczył limit miejsca. Obsługuję już niektóre przypadki błędów z kodami stanu HTTP (401 dla uwierzytelnienia, 403 dla autoryzacji i 404 dla zwykłych identyfikatorów URI niepoprawnego żądania). Przejrzałem błogosławione kody błędów HTTP, ale żaden z zakresów 400–417 nie wydaje się odpowiedni do zgłaszania błędów specyficznych dla aplikacji. Na początku kusiło mnie, aby zwrócić błąd aplikacji z 200 OK i konkretnym ładunkiem XML (tj. Zapłać nam więcej, a dostaniesz potrzebną pamięć!), Ale przestałem myśleć o tym i wydaje się, że mydło (/ wzruszając ramionami). Poza tym wydaje mi się, że dzielę odpowiedzi na błędy na osobne przypadki, ponieważ niektóre są oparte na kodzie stanu HTTP, a inne na treści.

Więc jakie są zalecenia branżowe? Dobre praktyki (proszę wyjaśnić dlaczego!), A także, od klienta pow, jaki rodzaj obsługi błędów w interfejsie API REST ułatwia życie kodu klienta?

Remus Rusanu
źródło
7
Aby wyjaśnić: nie jestem tak bardzo zainteresowany tym, który konkretny kod stanu HTTP powinien zostać zwrócony, ale czy dobrą praktyką REST jest łączenie błędów ładunku z kodami stanu HTTP, czy lepiej polegać wyłącznie na ładunku.
Remus Rusanu
3
Podręcznik projektowania interfejsu API REST dość dobrze omawia ten temat.
Remus Rusanu,
12
Pytanie nie wymaga opinii, ale wskazówek / zaleceń i powinno zostać ponownie otwarte i wykorzystane jako odniesienie. Na czym polegało zamknięcie w 2016 r. Pytania, które powstało w 2009 r., Ma ponad 400 głosów i żadna z istniejących odpowiedzi opartych na opiniach
Michael Freidgeim
4
Większość nie wspomniała, ale użycie kodów błędów HTTP może prowadzić do problemów związanych z główną przyczyną problemu. HTTP jest protokołem transportowym, a 404 powinien wskazywać, że wystąpił problem z poziomem transportu URL na poziomie transportu (np. Zła ścieżka). Jeśli aplikacja nie może znaleźć zestawu danych według swojego identyfikatora, jest to błąd na poziomie aplikacji (nie błąd poziomu transportu), a błąd 404, jak sugerują użytkownicy kodu stanu HTTP, może prowadzić do błędnych wniosków. Generalnie nie podoba mi się mieszanie warstwy transportu i aplikacji przy użyciu kodów statusu.
SCI

Odpowiedzi:

220

Na początku kusiło mnie, aby zwrócić błąd aplikacji z 200 OK i konkretnym ładunkiem XML (tj. Zapłać nam więcej, a dostaniesz potrzebną pamięć!), Ale przestałem myśleć o tym i wydaje się, że mydło (/ wzruszając ramionami).

Nie zwróciłbym 200, chyba że naprawdę nie było nic złego w żądaniu. Z RFC2616 , 200 oznacza „żądanie się powiodło”.

Jeśli limit miejsca klienta zostanie przekroczony (z jakiegokolwiek powodu), zwrócę 403 (zabronione):

Serwer zrozumiał żądanie, ale odmawia jego spełnienia. Autoryzacja nie pomoże, a prośba NIE POWINNA zostać powtórzona. Jeśli metoda żądania nie była HEAD, a serwer chce podać do publicznej wiadomości, dlaczego żądanie nie zostało spełnione, POWINIEN opisać przyczynę odmowy w jednostce. Jeśli serwer nie chce udostępnić tych informacji klientowi, zamiast tego można użyć kodu stanu 404 (Nie znaleziono).

To mówi klientowi, że żądanie było OK, ale nie powiodło się (coś, czego 200 nie robi). Daje to również możliwość wyjaśnienia problemu (i jego rozwiązania) w treści odpowiedzi.

Jakie jeszcze konkretne warunki błędu miałeś na myśli?

Rich Apodaca
źródło
6
Czy powinienem zawrzeć mój szczegółowy komunikat o błędzie w treści, tj. para kod / ciąg XML? Jak klienci najlepiej sobie z tym radzą? Na przykład wiem, że klienci korzystający z C # WebRequest wyrzucą „Bad Request” lub „Forbidden” i nie podadzą odpowiedzi.
Remus Rusanu
18
Treść „403” powinna zawierać szczegóły błędu. To, czy klient jest przygotowany na wykorzystanie informacji, to inna historia. Najbardziej sensowne jest, aby ten format był taki sam jak format dla wszystkich innych ładunków (np. XML, JSON).
Rich Apodaca
1
... a jeśli szczegóły nie zostaną zwrócone w 403, zamiast tego można użyć „404” (nie wydaje mi się to najlepszą opcją).
Rich Apodaca
6
Opcja 404 dotyczy zdarzenia, w którym 403 może ujawnić szczegółowe informacje o aplikacji, o których nie chcesz, aby nieuprawnieni użytkownicy wiedzieli - na przykład, jeśli użytkownik niebędący administratorem trafi na adres URL tylko dla administratora, możesz nie chcieć tego użytkownika aby wiedzieć, że jest to prawidłowy adres URL dla administratorów itp. W tym przypadku jednak 403 jest całkowicie odpowiedni.
Greg Campbell,
16
Czuję, że to dość niepomocna odpowiedź. Myślałem, że ważniejszy aspekt dotyczy tego, czy statusy powinny być używane wyłącznie, czy informacje o błędzie powinny zostać zwrócone w ładunku, czy w obu, itd. A następnie, w jaki sposób należy dodać informacje do ładunku. Zastosowany konkretny status dotyczy tylko jednego określonego aspektu pytania.
Manachi
584

Świetny zasób, aby wybrać prawidłowy kod błędu HTTP dla swojego interfejsu API: http://www.codetinkerer.com/2015/12/04/choosing-an-http-status-code.html

Fragment artykułu:

Gdzie zacząć:

wprowadź opis zdjęcia tutaj

2XX / 3XX:

wprowadź opis zdjęcia tutaj

4XX:

wprowadź opis zdjęcia tutaj

5XX:

wprowadź opis zdjęcia tutaj

Omar Ali
źródło
1
422 Jest szczególnie rozszerzeniem WebDAV. Myślę, że nie powinno tu być.
Mario,
@Mario W interfejsie API Ruby on Rails idiomatyczne jest zwracanie 422 w odpowiedzi na warunki tu określone. Wiele dobrego już podąża za tym podejściem. Do czego zastąpiłbyś zastosowania 422?
Kelsey Hannan
zwykły stary 400
Andbdrew
Dziękuję Ci. Co oznacza „Czy wściekłość rezygnujesz z Internetu?”?
RoutesMaps.com
@ Crimean.us google.com/search?q=define+rage-quit
Omar Ali
87

Głównym wyborem jest to, czy chcesz traktować kod stanu HTTP jako część interfejsu API REST, czy nie.

Oba sposoby działają dobrze. Zgadzam się, ściśle mówiąc, jednym z pomysłów REST jest to, że powinieneś używać kodu statusu HTTP jako części swojego API (zwróć 200 lub 201 dla udanej operacji i 4xx lub 5xx w zależności od różnych błędów). , nie ma policji REST. Możesz robić co chcesz. Widziałem znacznie bardziej skandaliczne interfejsy API inne niż REST nazywane „RESTful”.

W tym momencie (sierpień 2015) zalecamy używanie kodu stanu HTTP jako części interfejsu API. Teraz o wiele łatwiej jest zobaczyć kod powrotu podczas korzystania z frameworków niż w przeszłości. W szczególności łatwiej jest teraz zobaczyć przypadek zwrotu innej niż 200 i treść odpowiedzi innych niż 200 niż w przeszłości.

Kod stanu HTTP jest częścią interfejsu API

  1. Musisz starannie wybrać kody 4xx, które pasują do twoich błędów. Jako ładunek, który zawiera subkod i komentarz opisowy, możesz dołączyć wiadomość odpoczynku, XML lub zwykły tekst.

  2. Klienci będą musieli skorzystać z frameworka oprogramowania, który umożliwi im uzyskanie kodu stanu na poziomie HTTP. Zwykle wykonalne, nie zawsze proste.

  3. Klienci będą musieli rozróżniać kody stanu HTTP wskazujące na błąd komunikacji i własne kody stanu wskazujące na problem na poziomie aplikacji.

Kod statusu HTTP NIE jest częścią twojego interfejsu API

  1. Kod stanu HTTP będzie zawsze wynosił 200, jeśli aplikacja otrzyma żądanie, a następnie odpowie na nie (zarówno przypadki powodzenia, jak i błędy)

  2. WSZYSTKIE odpowiedzi powinny zawierać informacje „koperta” lub „nagłówek”. Zazwyczaj coś takiego:

    koperta_wer: 1.0
    status: # użyj dowolnych kodów. Zarezerwuj kod do sukcesu.
    msg: "ok" # Ludzki ciąg znaków, który odzwierciedla kod. Przydatne do debugowania.
    data: ... # Dane odpowiedzi, jeśli istnieją.
  3. Ta metoda może być łatwiejsza dla klientów, ponieważ status odpowiedzi jest zawsze w tym samym miejscu (nie są potrzebne subkody), bez ograniczeń kodów, nie trzeba pobierać kodu stanu na poziomie HTTP.

Oto post z podobnym pomysłem: http://yuiblog.com/blog/2008/10/15/datatable-260-part-one/

Główne kwestie:

  1. Pamiętaj o podaniu numerów wersji, aby w razie potrzeby później zmienić semantykę interfejsu API.

  2. Dokument...

Larry K.
źródło
8
Ty. Opcja 2 wydaje się jednak mydłem w ubraniach wypoczynkowych ...
Remus Rusanu
138
Nie, tunelowanie wszystkiego przez 200 wcale nie jest spokojne. Uniemożliwia pośrednikom zrozumienie wyniku operacji, która zabije dowolną formę buforowania, ukrywa semantykę operacji i narzuca zrozumienie treści wiadomości w celu przetworzenia błędu, naruszając samoograniczenie wiadomości.
SerialSeb
13
Zwracanie szczegółowych informacji o błędzie z wartością 200 może nie być RESTful, ale mimo to jest to przydatna odpowiedź (jeśli zignorujesz uwagę „Oba sposoby są spokojne”) ... Większy punkt może być taki, że interfejs API RESTful może nie być najlepszą opcją dla OP.
MB.
3
Wydaje się, że istnieje ogólne zrozumienie, że możesz robić co chcesz z protokołem HTTP i nadal być „RESTY”, to nieprawda. Użyj protokołu do tego, co jest napisane, to jedna z podstawowych idei REST. Więc kod stanu musi być częścią twojego protokołu.
Ariel M.,
Celem kodów statusu jest zapewnienie wspólnego języka zrozumienia dla różnych języków programowania, ram i podejść. Znaczenie kodów stanu jest zbliżone do uniwersalnego: twoje niestandardowe ciało - które z natury zwiększa złożoność dzięki niestandardowej składni, której muszą nauczyć się użytkownicy interfejsu API - nie jest.
Kelsey Hannan
40

Pamiętaj, że jest więcej kodów statusu niż te zdefiniowane w RFC HTTP / 1.1, rejestr IANA znajduje się na stronie http://www.iana.org/assignments/http-status-codes . W przypadku, o którym wspomniałeś, kod stanu 507 brzmi dobrze.

Julian Reschke
źródło
3
Hmm, choć na pierwszy rzut oka „507 Niewystarczające miejsce” wydaje się być odpowiednie, chętnie bym go używał, ponieważ jest przeznaczony jako (dość specyficzne) rozszerzenie WebDAV, a nie ogólne „hej, masz za mało miejsca” wyjątek. Mimo to przypuszczam, że mógłbyś go użyć.
Maks
1
Nie, to wcale nie jest specyficzne dla WebDAV. Istnieje powód, dla którego istnieje rejestr kodów stanu HTTP.
Julian Reschke
25
Nie zgadzam się z 507tym celem. Moją interpretacją 507jest to, że na serwerze brakuje miejsca, a nie, że na koncie brakuje miejsca.
Patrick,
11
Zgadzam się z Patrickiem. 5xxbłędy dotyczą błędów związanych z serwerem.
Sean
10
418: „Jestem czajnikiem”, co sugeruje, że miejsce do przechowywania jest za mało (tak jak czajniczek jest mały), a nie za duże, a zatem brakuje mu miejsca.
Steve Konves,
22

Jak zauważyli inni, istnienie jednostki odpowiedzi w kodzie błędu jest całkowicie dopuszczalne.

Pamiętaj, że błędy 5xx są po stronie serwera, czyli klient nie może nic zmienić w swoim żądaniu, aby żądanie zostało zrealizowane. Jeśli limit klienta zostanie przekroczony, to z pewnością nie jest to błąd serwera, więc należy unikać 5xx.

SerialSeb
źródło
Nie zgodziłbym się. Przekroczony limit byłby błędem serwera (5xx), ponieważ: Żądanie klienta jest prawidłowe i zostałoby zrealizowane, gdyby w ramach limitu, co wyklucza 400 serwerów.
mikek3332002,
3
Ale serwer nie zrobił nic złego.
Charlie Schliesser
20

Istnieją dwa rodzaje błędów. Błędy aplikacji i błędy HTTP. Błędy HTTP mają po prostu poinformować program obsługi AJAX, że wszystko poszło dobrze i nie należy go używać do niczego innego.

5xx błąd serwera

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported
506 Variant Also Negotiates (RFC 2295 )
507 Insufficient Storage (WebDAV) (RFC 4918 )
509 Bandwidth Limit Exceeded (Apache bw/limited extension)
510 Not Extended (RFC 2774 )

2xx Sukces

200 OK
201 Created
202 Accepted
203 Non-Authoritative Information (since HTTP/1.1)
204 No Content
205 Reset Content
206 Partial Content
207 Multi-Status (WebDAV)

Jednak sposób zaprojektowania błędów aplikacji zależy od Ciebie. Przepełnienie stosu na przykład wysyła obiekt z response, datai messagewłaściwości. Odpowiedź, która moim zdaniem zawiera truelub falsewskazuje, czy operacja się powiodła (zwykle w przypadku operacji zapisu). Dane zawierają ładunek (zwykle do operacji odczytu), a komunikat zawiera wszelkie dodatkowe metadane lub przydatne komunikaty (takie jak komunikaty o błędach, gdy responsefalse).

aleemb
źródło
1
400 jest również pomocny do wskazania problemu w aplikacji klienckiej.
dolmen
19

Wiem, że jest to bardzo późno na imprezę, ale teraz, w 2013 roku, mamy kilka rodzajów mediów do obsługi obsługi błędów w typowy sposób rozproszony (RESTful). Zobacz „vnd.error”, application / vnd.error + json ( https://github.com/blongden/vnd.error ) i „Szczegóły problemu dla interfejsów API HTTP”, application / problem + json ( https: // tools. ietf.org/html/draft-nottingham-http-problem-05 ).

Jørn Wildt
źródło
2
Dzięki za linki. Projekt-nottingham-http-problem jest teraz proponowanym standardem: datatracker.ietf.org/doc/rfc7807
seanf
9

Zgoda. Podstawową filozofią REST jest korzystanie z infrastruktury internetowej. Kody stanu HTTP to struktura przesyłania wiadomości, która umożliwia stronom komunikowanie się ze sobą bez zwiększania ładunku HTTP. Są one już ustanowione uniwersalnymi kodami przekazującymi status odpowiedzi, a zatem, aby być naprawdę RESTful, aplikacje muszą używać tej struktury do komunikowania statusu odpowiedzi.

Wysłanie odpowiedzi na błąd w kopercie HTTP 200 wprowadza w błąd i zmusza klienta (konsumenta interfejsu API) do przeanalizowania komunikatu, najprawdopodobniej w niestandardowy lub zastrzeżony sposób. To również nie jest wydajne - zmusisz swoich klientów do analizowania ładunku HTTP za każdym razem, aby zrozumieć „prawdziwy” status odpowiedzi. Zwiększa to przetwarzanie, dodaje opóźnienia i tworzy środowisko, w którym klient może popełniać błędy.

Kingz
źródło
3
Niezależnie od tego, czy masz udaną odpowiedź, czy reakcję na błąd, najprawdopodobniej przeanalizujesz odpowiedź. Jeśli jest to błąd, należy go przeanalizować, aby uzyskać komunikat o błędzie. Reakcje na błędy są na ogół małe i szybkie do przeanalizowania. Nie sądzę, że powinniśmy się martwić próbą optymalizacji, aby uniknąć analizowania odpowiedzi na błędy. Czy po prostu wyrzucisz odpowiedź błędu bez parsowania? Moim zdaniem nierozsądny.
AgilePro
3
Jeśli otrzymasz 200 OK, możesz również nie analizować go, w zależności od reguł biznesowych. Nie chodzi o to, czy analizujemy to przez cały czas, czy nie. Chodzi o cel - jaki jest cel 200 OK? Uszkadzasz zamiar, wysyłając komunikaty o błędach opakowane w 200 OK.
Kingz
1
„Jaki jest cel 200 OK?” - wskazanie powodzenia warstwy transportowej. Żądanie zostało pomyślnie odebrane i udzielono odpowiedzi, wystąpił problem związany z aplikacją, który nie miał nic wspólnego z HTTP. +++ Odwrotnie: wysłanie 404 w świecie REST oznacza, że coś nie zostało znalezione, może URL jest po prostu zły lub zasób, który ma być przetwarzany, lub nic innego nie znaleziono. Bez parsowania wiadomości nie możesz. IMHO REST to tylko łączenie warstw.
maaartinus
Konfuzja jest normą. Zapewnia ci składnię, z którą możesz sobie poradzić, i która odpowiada twojemu tokowi rozumowania, i pozwala skupić się na warstwie biznesowej. Uzgodniono, że komunikat o statusie transportu później - taki był przede wszystkim cel - REST nie został wymyślony / zaproponowany jednocześnie z HTTP - przyszedł później i po prostu postanowił wykorzystać istniejącą infrastrukturę do reprezentowania stanów i ich ZMIAN.
Kingz
5

Proszę trzymać się semantyki protokołu. Użyj 2xx dla pomyślnych odpowiedzi i 4xx, 5xx dla odpowiedzi na błędy - czy to twoich wyjątków biznesowych czy innych. Gdyby użycie 2xx dla jakiejkolwiek odpowiedzi było zamierzonym przypadkiem użycia w protokole, nie miałyby przede wszystkim innych kodów stanu.

rahil008
źródło
3

Nie zapomnij również o błędach 5xx w przypadku błędów aplikacji.

W takim przypadku co z 409 (konfliktem)? Zakłada się, że użytkownik może rozwiązać problem, usuwając przechowywane zasoby.

W przeciwnym razie może również działać 507 (nie do końca standardowy). Nie użyłbym 200, chyba że użyjesz 200 do błędów w ogóle.

Kathy Van Stone
źródło
-1

Jeśli limit klienta zostanie przekroczony, oznacza to błąd serwera, unikaj w tym przypadku 5xx.

stała renta
źródło
2
Dlaczego warto unikać błędów serii 5xx, jeśli dotyczą one błędów serwera?
mikek3332002,
6
„Przekroczono limit klienta” nie jest imho błędem serwera, to ograniczenie klienta i powinno być poniżej 4xx.
MyGGaN