Kiedy używać kodu stanu 404 w interfejsie API

58

Pracuję nad projektem i po kłótni z ludźmi w pracy przez ponad godzinę. Postanowiłem wiedzieć, co mogą powiedzieć ludzie korzystający z wymiany stosów.

Piszemy API dla systemu, istnieje zapytanie, które powinno zwrócić drzewo Organizacji lub drzewo Celów.

Drzewo Organizacji to organizacja, w której użytkownik jest obecny. Innymi słowy, drzewo to powinno zawsze istnieć. W organizacji drzewo celów powinno być zawsze obecne. (od tego zaczął się argument). W przypadku, gdy drzewo nie istnieje, mój współpracownik zdecydował, że dobrze będzie odpowiedzieć na kod stanu 200. A potem zaczął prosić mnie o naprawienie mojego kodu, ponieważ aplikacja się rozpadała, gdy nie było drzewa.

Spróbuję oszczędzić płomieni i furii.

Zasugerowałem podniesienie błędu 404, gdy nie ma drzewa. To przynajmniej dałoby mi znać, że coś jest nie tak. Korzystając z 200, muszę dodać specjalne sprawdzenie do mojej odpowiedzi w wywołaniu zwrotnym powodzenia, aby obsłużyć błędy. Oczekuję, że otrzymam obiekt, ale mogę otrzymać pustą odpowiedź, ponieważ nic nie zostanie znalezione. Oznaczenie odpowiedzi jako 404 wydaje się całkowicie uczciwe. A potem wybuchła wojna i dostałem wiadomość, że nie rozumiem schematu kodu statusu HTTP. Więc jestem tutaj i pytam, co jest nie tak z 404 w tym przypadku? Dostałem nawet argument „Nic nie znalazłem , więc dobrze jest zwrócić 200”. Uważam, że to źle, ponieważ drzewo powinno być zawsze obecne. Jeśli nic nie znaleźliśmy i czegoś oczekujemy, powinno to być 404.

Więcej informacji,

Zapomniałem dodać pobrane adresy URL.

Organizacje

/OrgTree/Get

Cele

/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...

Mój błąd, oba parametry są wymagane. Jeśli podana jest jakakolwiek wersjaData, którą można przeanalizować z datą, zwróci poprawkę zamknięcia. Jeśli wpiszesz coś w przeszłości, zwróci pierwszą wersję. Jeśli przez Id z identyfikatorem, który nie istnieje, podejrzewam, że zwróci pustą odpowiedź z 200.

Dodatkowy

Ponadto uważam, że najlepszą odpowiedzią na problem jest tworzenie domyślnych obiektów podczas tworzenia organizacji, brak drzewa nie powinien być prawidłowym przypadkiem i powinien być postrzegany jako zachowanie niezdefiniowane. Nie ma możliwości korzystania z konta bez obu drzew. Z tych powodów powinni być zawsze obecni.

też połączyłem to (jeden podobny, ale nie mogę go znaleźć)

http://viswaug.files.wordpress.com/2008/11/http-headers-status1.png

Loïc Faure-Lacroix
źródło
Wyjaśnij: w jaki sposób aplikacja może się rozpaść, gdy nie ma drzewa, jeśli zawsze istnieje drzewo z góry ? (Zgadzam się z tobą, wygląda na 404)
Andres F.,
Cóż, kod nie sprawdzał wartości zerowej i analizował ciąg json i jako obiekt. W pewnym miejscu kodu ładowany obiekt nie jest obecny, ponieważ nie można go znaleźć wewnętrznie.
Loïc Faure-Lacroix
4
Byłoby wyraźniej, gdybyś podał identyfikatory URI dla zasobu, do którego próbujesz uzyskać dostęp. Jeśli to / goli / zwrócisz 200 i pusty zestaw. Jeśli próbujesz uzyskać dostęp do / goal / {goal_id}, to zwracasz 404. Jeśli zwróciłeś 404 dla żądania / goal /, oznacza to, że identyfikator URI nie istnieje i nie powinien być już używany.
imel96
1
W obu przypadkach pytanie pozostaje aktualne. Co powinieneś /GoalTree/GetById?versionId=CompletelyInvalidIDzwrócić? Niepowodzenie, ponieważ wymieniony zasób /GoalTree/GetById?versionId=CompletelyInvalidIDdosłownie nie został znaleziony.
2
Świetnie, teraz dyskusja zmieniła się z pracy na internety! Teraz jest nie do powstrzymania!
Carlos Campderrós

Odpowiedzi:

79

W razie wątpliwości zajrzyj do dokumentacji . Przejrzenie definicji W3C dla kodów statusu HTTP daje nam to:

200 OK - Żądanie powiodło się. Informacje zwrócone wraz z odpowiedzią zależą od metody użytej w żądaniu.

404 Nie znaleziono - serwer nie znalazł nic pasującego do URI żądania.

W kontekście interfejsu API bardzo zależy to od sposobu tworzenia zapytań i pobierania obiektów. Ale moja interpretacja zawsze była taka:

  • Jeśli poproszę o konkretny obiekt i istnieje on 200kod powrotu , jeśli nie istnieje, zwróć poprawny 404kod.
  • Ale jeśli poproszę o zestaw obiektów pasujących do zapytania, zestaw zerowy jest prawidłową odpowiedzią i chcę, aby został zwrócony z 200kodem. Uzasadnieniem tego jest to, że zapytanie było prawidłowe, powiodło się, a zapytanie nic nie zwróciło.

Więc w tym przypadku masz rację , usługa nie szuka „konkretnej rzeczy”, żąda konkretnej rzeczy, jeśli czegoś nie znaleziono, powiedz to wyraźnie.

Myślę, że Wikipedia mówi najlepiej:

200 OK - ... Rzeczywista odpowiedź będzie zależeć od użytej metody żądania. W żądaniu GET odpowiedź będzie zawierać encję odpowiadającą żądanemu zasobowi.

404 Nie znaleziono - Żądany zasób nie został znaleziony, ale może być ponownie dostępny w przyszłości. Kolejne żądania klienta są dopuszczalne.

Wydaje mi się to całkiem jasne.

Odnośnie przykładowych żądań

/GoalTree/GetByDate?versionDate=...
/GoalTree/GetById?versionId=...

W przypadku formatu zawsze zwracasz najbliższą wersję do tej daty. Nigdy nie zwróci obiektu, więc zawsze powinien powracać 200 OK. Nawet jeśli byłby w stanie przyjąć zakres dat, a logika polegała na zwróceniu wszystkich obiektów w tym przedziale czasowym, zwracając 200 OK - 0 Wyniki są w porządku, ponieważ właśnie o to chodziło w żądaniu - zbiór rzeczy spełniających te kryteria.

To ostatnie jest jednak inne, ponieważ pytasz o konkretny obiekt , prawdopodobnie unikalny, o tej tożsamości. Zwrócenie 200 OKw tym przypadku jest nieprawidłowe, ponieważ żądany zasób nie istnieje i nie został znaleziony .

Odnośnie wybierania kodów statusu

  • Kody 2xx Powiedz UA, że zrobił to dobrze , żądanie zadziałało. Może to robić w przyszłości.
  • Kody 3xx Powiedz UA, o co prosiłeś, prawdopodobnie działało, ale ta sprawa jest teraz gdzie indziej. W przyszłości UA może rozważyć przejście do przekierowania .
  • Kody 4xx Powiedz UA, że coś zrobiło źle , skonstruowane przez nią żądanie jest nieprawidłowe i nie powinno się tego próbować ponownie, bez żadnych modyfikacji.
  • 5xx kody Powiedz UA, że serwer jest jakoś uszkodzony . Ale hej, to zapytanie może działać w przyszłości, więc nie ma powodu, aby nie próbować go ponownie. (z wyjątkiem 501, co jest bardziej kwestią 400).

Wspomniałeś w komentarzu za pomocą kodu 5xx, ale twój system działa. Zostało zadane zapytanie, które nie działa i musi zostać przekazane do UA. Bez względu na to, jak je pokroisz, jest to terytorium 4xx.

Rozważ kosmitów pytających o nasz układ słoneczny

Alien: Komputer, proszę powiedz mi wszystkie planety, które zamieszkują ludzie.

Komputer: znaleziono 1 wynik. Ziemia

Alien: Komputer, opowiedz mi o Ziemi .

Komputer: Ziemia - w większości nieszkodliwy.

Alien: Komputer, opowiedz mi o wszystkich planetach, które zamieszkują ludzie, poza pasem asteroid.

Komputer: znaleziono 0 wyników.

Alien: Komputer, proszę zniszcz Ziemię.

Komputer: 200 OK.

Alien: Komputer, opowiedz mi o Ziemi .

Komputer: 404 - Nie znaleziono

Alien: Komputer, proszę powiedz mi wszystkie planety, które zamieszkują ludzie.

Komputer: znaleziono 0 wyników.

Alien: Zwycięstwo potężnego imperium Irken!

Nick Tsai
źródło
4
+1 To nie jest zapytanie, które nie zwraca wyników. To tak, jakby poprosić przeglądarkę o znaną stronę internetową i nie znaleźć jej. Dokładnie po co jest 404.
Andres F.,
2
@ imel96 zapominasz, że ciąg zapytania jest częścią adresu URL.
Loïc Faure-Lacroix
1
@ LegoStormtroopr Twój zabawny „obcy” przykład działa, ponieważ wszechświat NIE jest nieprawidłowy, gdy Ziemia nie istnieje. Ale zgodnie z wyjaśnieniem OP jego system musi obejmować drzewo. Bez drzewa system nie działa.
Andres F.,
1
@LegoStormtroopr wyobraź sobie tabelę bazy danych. Przeszukujesz tabelę, czasem uzyskujesz wynik, a czasem nie. Tabela jest Twoim zasobem, zawsze tam jest, niezależnie od tego, czy zwraca wiersze, czy nie. Tabela jest identyfikowalna, ma nazwę (podobnie jak zasoby http mają identyfikatory URI). Wiersze nie są, pasują tylko do niektórych parametrów. Nawet w bazie danych, jeśli wykonasz aktualizację, która nic nie pasuje, pojawi się komunikat „Wpłynęło 0 0 wierszy”.
imel96
2
@LegoStormtroopr masz już odpowiedź. Jeśli chcą ponownie przypisać / GoalTree / GetById? VersionId = x, powinien zwrócić 301 z nagłówkiem Location ustawionym na / GoalTree / Id / x.
imel96
11

Ignorując fakt, że / GoalTree / Get * wygląda jak czasownik, a nie zasoby, zawsze powinieneś zwrócić 200, ponieważ URI / GoalTree / Get * reprezentują zasoby, które są zawsze dostępne dla dostępu i nie jest to błąd klienta, jeśli nie ma drzewa w wyniku prośba. Zwróć 200 z pustym zestawem, gdy nie ma elementu do zwrotu.

Używasz 404, jeśli zasób nie zostanie znaleziony, a nie, gdy nie ma encji.

Innymi słowy, jeśli chcesz zwrócić 404 za swoje obiekty, podaj im ich własne identyfikatory URI.

imel96
źródło
1
Hmm To ma sens. 404 jest błędem użytkownika , ale jak wyjaśnia OP, w rzeczywistości jest to błąd systemowy ; prośba użytkownika jest całkowicie ważna! Nie zgadzam się, że 200 jest właściwą odpowiedzią, ponieważ „brak drzewa” jest błędem .
Andres F.,
@ imel96 Wolałbym, aby zawsze zwracano prawidłowe byty zamiast pustego / kodu statusu 4xx / 5xx. Gdyby to był tylko ja, zwróciłbym prawidłową jednostkę, tak jak na przykład wiki. Mniejszy ból głowy bez konieczności obsługi błędów. W tej chwili powiedziałbym, że jest prawie jak 500. System jest w nieokreślonym stanie, to nie powinno się zdarzyć. A zwrot OK nie ma sensu. 404 dotyczące rfc również nie ma sensu. Więc kiedy nic nie ma sensu ... tylko 500 ma sens!
Loïc Faure-Lacroix
@Sybiam dobrze, poprosiłeś o kod stanu HTTP, który jest bardzo dobrze zdefiniowany. Pod tym względem, nawet jeśli logika biznesowa mówi, że to błąd, nie oznacza to, że w systemie występuje błąd serwera HTTP. W twoim przypadku zrozumiał twoje zapytanie, przetworzył twoje zapytanie i po prostu zdarzyło się, że wynikiem nie jest żaden byt. Więc nie możesz również użyć 500. Przynajmniej rozważ nadanie swoim obiektom odpowiednich URI i sprawdź, czy rfc ma większy sens, czy nie.
imel96
+1 Jeśli masz interfejs API REST (każda jednostka ma własną ścieżkę), możesz zwrócić 404, ale twoje ścieżki są czasownikami i zawsze zostaną znalezione.
Stop Harming Monica,
@OrangeDog: /GoalTree/GetById?versionId=12345 jest idealnie dobrym identyfikatorem URI (przynajmniej względnym), który identyfikuje określony zasób, a mianowicie dane odpowiadające identyfikatorowi wersji 12345w systemie. Jeśli nie ma danych o takim identyfikatorze, odpowiedź HTTP 404 jest całkowicie odpowiednia. Oczywiście treść odpowiedzi powinna w każdym przypadku zawierać odpowiednio sformatowaną odpowiedź (np. JSON, jeśli tego oczekują typowi klienci żądający takich zasobów), wskazując konkretny charakter i przyczynę błędu.
Ilmari Karonen
7

To interesujące pytanie, ponieważ chodzi o specyfikację systemu.

Odpowiedź imel96 przekonała mnie, że 404 nie byłby właściwą odpowiedzią, ponieważ rodzina kodów 4xx dotyczy głównie błędów użytkownika / klienta , i to nie jest jeden. Adres URL jest poprawnie sformułowany i drzewo musi tam być; jeśli nie, system jest niespójny!

Dlatego jest to błąd serwera , tzn. Coś z rodziny 5xx. Prawdopodobnie ogólny błąd wewnętrzny serwera 500 lub usługa 503 niedostępna (usługa polega na „ściągnięciu drzewa, które musi tam być”).

Andres F.
źródło
2
Nieprawda, użytkownik jest w błędzie, ponieważ poprosił o coś, co nie istnieje .
@LegoStormtroopr Pytanie o coś, co nie istnieje, nie zawsze jest błędem. Jeśli poprosisz o zasób sieciowy, a sieć nie działa, oznacza to błąd sieci .
Andres F.,
1
@LegoStormtroopr Poza tym drzewo musi istnieć; system nie może bez niego funkcjonować, zgodnie z wyjaśnieniem PO. Dlatego warto poprosić o ten zasób; jeśli go nie ma, musi to być błąd systemowy (lub serwerowy).
Andres F.,
2
@Sybiam Jeśli zamierzasz wybrać trasę kodu 5xx, 503 oznacza „Usługa 503 niedostępna - serwer obecnie nie jest w stanie obsłużyć żądania z powodu tymczasowego przeciążenia lub konserwacji serwera”. Twój serwer nie jest przeciążony, nie może znaleźć żądania. Dodatkowo kody 5xx dotyczą sytuacji, gdy „serwer jest świadomy, że popełnił błąd lub nie jest w stanie wykonać żądania”
1
@AndresF. Szczerze mówiąc, kod 500 jest prawdopodobnie w porządku. Biorąc pod uwagę, jak pytanie zmieniało się w czasie, zadziałałoby. Przeważnie walczę przeciwko zwrotowi 200, jeśli wszystko nie jest w porządku.
6

Powiedziałbym, że może być poprawny kod odpowiedzi 200 lub 404 , w zależności od tego, jak spojrzysz na sytuację.

Chodzi o to, że kody odpowiedzi HTTP są zdefiniowane w kontekście serwera , który może dostarczać różne zasoby na podstawie ich adresów URL. W tym kontekście znaczenia 200 OKi 404 Not Foundsą całkowicie jednoznaczne: pierwsza mówi „oto zasób, o który prosiłeś”, a druga mówi „przepraszam, nie mam takich zasobów”.

Jednak w twojej sytuacji istnieje dodatkowa warstwa aplikacji między serwerem HTTP a rzeczywistymi żądanymi zasobami (drzewami). Aplikacja zajmuje rodzaj przestrzeni pośredniej, która nie jest dobrze zaadresowana w specyfikacji HTTP.

Z punktu widzenia serwera sieciowego, zastosowanie wygląda trochę jak zasób: to zazwyczaj plik na serwerze, zidentyfikowanego przez (część) adres URL, podobnie jak innych zasobów (np statycznych plików) serwer może służyć. Z drugiej strony jest to dziwny rodzaj zasobu, ponieważ składa się z kodu wykonywalnego, który dynamicznie określa treść, a nawet potencjalnie kod statusu odpowiedzi, dzięki czemu zachowuje się w pewien sposób bardziej jak mini-serwer.

W szczególności, w twoim przypadku serwer WWW może dobrze zlokalizować aplikację, ale aplikacja nie może zlokalizować żądanego podkatalogu (drzewa). Teraz, jeśli uważasz aplikację za rozszerzenie serwera , a podelement (drzewo) za rzeczywisty zasób, to odpowiednia jest odpowiedź 404 : serwer jedynie przekazał zadanie znalezienia rzeczywistego zasobu do aplikacji , które jej się nie udało.

Z drugiej strony, jeśli twoim zdaniem jest to, że aplikacja jest żądanym zasobem , serwer sieci powinien oczywiście zwrócić odpowiedź 200 ; w końcu aplikacja została znaleziona i wykonana poprawnie. Oczywiście w tym przypadku aplikacja powinna faktycznie zwrócić poprawną treść odpowiedzi w oczekiwanym formacie, wskazując (używając dowolnego protokołu wyższego poziomu, który koduje ten format), że nie znaleziono żadnych rzeczywistych danych pasujących do zapytania.

Oba te punkty widzenia mogą mieć sens. W większości przypadków , przynajmniej w przypadku aplikacji przeznaczonych do bezpośredniego dostępu przez HTTP za pomocą zwykłej przeglądarki internetowej, wolałbym poprzedni widok : użytkownik zasadniczo nie dba o szczegóły wewnętrzne, takie jak różnica między serwerem a aplikacją, po prostu dbać o to, czy dane, których chcieli, są, czy nie.

Jednak w konkretnym przypadku aplikacji zaprojektowanej do komunikowania się z innymi programami komputerowymi przy użyciu niestandardowego protokołu API wysokiego poziomu, wykorzystującego HTTP tylko jako warstwę transportową niskiego poziomu , należy argumentować na korzyść tego drugiego widoku : dla klienci współpracujący z taką aplikacją, wszystko, na czym naprawdę im zależy, na poziomie HTTP , to to, czy udało im się pomyślnie skontaktować z aplikacją, czy nie. Cała reszta jest w takich przypadkach często bardziej naturalnie komunikowana przy użyciu protokołu wyższego poziomu.


W każdym razie, niezależnie od tego, który z powyższych widoków preferujesz, jest kilka szczegółów, o których powinieneś pamiętać. Jednym z nich jest to, że w wielu przypadkach może istnieć znaczące rozróżnienie między (zasadniczo) pustym zasobem a nieistniejącym zasobem .

Na poziomie HTTP pusty zasób byłby po prostu oznaczony kodem 200 odpowiedzi i pustym ciałem odpowiedzi, natomiast nieistniejący zasób byłby wskazany przez odpowiedź 404 i treść zasobu wyjaśniającą brak zasobu. W protokole API wyższego poziomu zwykle wskazuje się na nieistniejący zasób za pomocą odpowiedzi na błąd, zawierającej odpowiedni kod / komunikat błędu specyficzny dla protokołu, natomiast pusta odpowiedź byłaby po prostu normalną strukturą odpowiedzi bez elementów danych.

(Zauważ, że zasób nie musi być dosłownie długi na zero bajtów, aby był „pusty” w sensie, o którym mowa powyżej. Na przykład wynik wyszukiwania bez pasujących elementów byłby liczony jako pusty w szerokim znaczeniu, tak jak wynik zapytania SQL z bez wierszy lub dokumentu XML nie zawierającego rzeczywistych danych).

Ponadto, oczywiście, jeśli aplikacja naprawdę nie wierzy, że żądana subresource powinno tam być, ale nie może go znaleźć, potem trzeci możliwy kod odpowiedzi istnieje: 500 Internal Server Error. Taka odpowiedź ma sens, jeśli istnienie zasobu jest założonym warunkiem wstępnym aplikacji, tak że jego brak koniecznie oznacza wewnętrzną awarię.

Wreszcie, należy zawsze pamiętać o prawie Postela :

Bądź konserwatywny w tym, co wysyłasz, i liberalny w tym, co otrzymujesz ”.

Niezależnie od tego, czy serwer powinien odpowiedzieć w konkretnej sytuacji odpowiedzią 200, czy 404, nie usprawiedliwia to, jako implementatora klienta, odpowiedniej obsługi odpowiedzi w sposób maksymalizujący niezawodną interoperacyjność. Oczywiście można argumentować, co oznacza „odpowiednie” postępowanie w różnych sytuacjach, ale z pewnością nie powinno to normalnie obejmować awarii lub „rozpadu”.

Ilmari Karonen
źródło
Dylemat dobrze wyjaśniony.
Marcel
nie ma dylematu. ta odpowiedź nie jest oparta na tym, jaki zasób jest zdefiniowany jak w powiązanym pliku rfc. zobacz mój komentarz pod odpowiedzią @LegoStormtroopr.
imel96
@ imel96: Wydaje mi się, że źle interpretujesz RFC 1630: akapit, który zacytowałeś we wcześniejszym komentarzu, w całości brzmi: „Znak zapytania („? ”, ASCII 3F hex) służy do wyznaczenia granicy między identyfikatorem URI zapytania obiekt i zestaw słów użytych do wyrażenia zapytania na tym obiekcie. Gdy ten formularz jest używany, połączony identyfikator URI oznacza obiekt, który wynika z zastosowania zapytania do oryginalnego obiektu. (moje podkreślenie). Tak więc jasne jest, że ciąg kwerendy jest rzeczywiście częścią URI (choć część przed ciągu kwerendy jest koniecznie, również ważny URI przez siebie) ...
Ilmari Karonen
... oraz że ten połączony identyfikator URI identyfikuje konkretny zasób, o który klient może poprosić, wysyłając ten identyfikator URI na serwer. W każdym razie RFC 2616 (HTTP) po prostu definiuje zasób jako „Obiekt danych sieci lub usługę, które można zidentyfikować za pomocą identyfikatora URI, zgodnie z definicją w sekcji 3.2”. i mówi dalej: „Jeśli chodzi o HTTP, jednolite identyfikatory zasobów to po prostu sformatowane ciągi znaków, które identyfikują - poprzez nazwę, lokalizację lub dowolną inną cechę - zasób”.
Ilmari Karonen
@IlmariKaronen masz rację. Pomyliłem HTTP z REST. Nadal nie wydaje się to właściwe, ponieważ nie jestem pewien, co możesz zrobić z zasobem o identyfikatorze URI, takim jak / GoalTree / Get? VersionDate =
2000BC
3

Co powiesz na 204 No Content? Sugeruje to, że Twoje zapytanie zostało przetworzone pomyślnie, ale nic nie zwraca. To wciąż „sukces”, ale pozwala zobaczyć, czy masz wyniki oparte na samym kodzie stanu.

modernserf
źródło
6
jeśli przeczytasz dalej specyfikację, „Ta odpowiedź ma przede wszystkim umożliwić wprowadzanie działań, które mają się odbyć bez powodowania zmiany w aktywnym widoku dokumentu agenta użytkownika”. Dlatego nie należy go używać do żądań GET.
imel96
3

Jeśli adres URL reprezentuje zasób, który nigdy nie istniał, zwróć 404 Nie znaleziono

Jeśli adres URL reprezentuje zasób, który jest pustą listą, zwróć pustą listę i 200 OK.

Przykład:

{
  total: 0,
  items: []
}

Jeśli adres URL reprezentuje zasób, który kiedyś istniał, zwróć 410 Gone.

Odnośnie dialogu Lego Szturmowca:

Alien: Computer, please tell me all planets that humans inhabit. GET /planets?inhabitedBy=humans

Computer: 200 OK. { total: 1, items:[{name:'Earth'}] }

Alien: Computer, please tell me about Earth. GET /planets/earth

Computer: 200 OK. {name:'Earth', status: 'Mostly Harmless'}

Alien: Computer, please tell me about all planets humans inhabit, outside the asteroid belt. GET /planets?inhabitedBy=humans&distanceFromSun=lots

Computer: 200 OK. {total:0, items:[] }

Alien: Computer, please destroy Earth. DELETE /planets/earth

Computer: 204 No Content. (or 202 Accepted if it takes some time to destroy Earth)

Alien: Computer, please tell me about Earth. GET /planets/earth

Computer: 410 Gone

Alien: Computer, please tell me all planets that humans inhabit. GET /planets?inhabitedBy=humans

Computer: 200 OK 0 {total: 0, items:[] }

Alien: Victory for the mighty Irken Empire!
Neil McGuigan
źródło
1

Z tego dźwięku jest to interfejs API do użytku wewnętrznego . Daje to przewagę przy stosowaniu dowolnego schematu, który daje największe korzyści , niezależnie od tego, czy jest to zgodne z księgą (specyfikacja), czy nie. Nie oznacza to, że całkowicie wymyślisz własne kody statusu, ale możesz nieco „wygiąć” reguły, jeśli jest to korzystne.

Zgadzam się z twoim stanowiskiem, że powinieneś otrzymać kod statusu, który pokazuje, że coś poszło nie tak. Po to właśnie są kody stanu. Dostajesz także korzyści z bibliotek, które zgłaszają wyjątki / etc. na kodzie stanu innym niż 200, abyś nie musiał jawnie sprawdzać (Możesz też napisać własne opakowanie, które to robi).

Zgadzam się również z punktem widzenia Andresa F., że 500 jest odpowiednie, ponieważ drzewo powinno istnieć. W praktyce jednak lubię dzielić błędy serwera na dwie kategorie. Coś nieoczekiwanego poszło nie tak i coś, co mogę praktycznie sprawdzić, poszło nie tak. Powoduje to następujące kody stanu,

  • 200 - Wszystko jest dobrze
  • 404 - Błędny adres URL
  • 409 - Coś poszło nie tak
  • 500 - Wystąpił nieoczekiwany błąd na serwerze

W twoim konkretnym przypadku możesz sprawdzić, czy drzewo istnieje po stronie serwera, a jeśli go nie ma, zwróć 409. Jest to oczekiwany błąd (wiesz, że może się zdarzyć, możesz to sprawdzić itp.) . Konflikt 409 to tylko moje osobiste preferencje, 5xx może być również odpowiedni, o ile możesz usiąść i zdecydować o tym ze swoim zespołem.

Kategoryzowanie takich kodów pomaga szybciej zidentyfikować rodzaj błędu, ale może przynieść korzyści poza organizacją. Często z błędami witryny nie chcesz, aby klient otrzymywał nieoczekiwane błędy, ponieważ może to powodować problemy związane z bezpieczeństwem i ujawniać luki w zabezpieczeniach, dlatego zwracany jest typowy błąd 500 „Wystąpił błąd”. i zaloguj pełny błąd na serwerze. Ale jeśli wystąpi oczekiwany błąd jako 409, wiesz, że bezpiecznie byłoby pokazać klientowi błąd i nie musisz zostawiać go w ciemności, co się stało. To tylko jedno praktyczne zastosowanie, które mogę opisać, ale istnieje wiele możliwości.

Jest to trochę kłopotliwe, ponieważ publikujesz to, ponieważ nie jesteś w stanie zgodzić się ze swoimi współpracownikami, ale brzmi to tak, jakbyście spierali się o semantykę i kto ma rację polityczną. Tak naprawdę nie ma znaczenia, kto jest bardziej odpowiedni, o ile można wymyślić system, który najbardziej przyniesie korzyści firmie.

Z drugiej strony, jeśli jest to publiczny interfejs API zgodny ze specyfikacjami tak blisko, jak to możliwe, ważniejsze byłoby uniknięcie zamieszania wśród społeczności.

Despertar
źródło
0

Biorąc to pod uwagę: jeśli człowiek ostatecznie korzysta z API (poprzez GUI), sugerowałbym robienie czegokolwiek, co ułatwia życie użytkownikowi końcowemu. Nieistnienie drzewa, gdy powinno ono istnieć, jest błędem „niespójności modelu domeny”. Błąd systemowy występuje, gdy zabraknie pamięci lub wystąpi inna awaria systemowa. Dlatego zwracanie 5xx jest niewłaściwe. Jak wspomniano powyżej, 4xx może być odpowiednie, jeśli samo drzewo ma swój własny identyfikator URI, co nie ma miejsca w tym przypadku. Ale oto, co 404 mówi klientowi: możesz próbować raz za razem, dopóki coś nie odzyskasz. Jeśli zwróciłeś 200, możesz zwrócić wystarczającą diagnostykę z powrotem do użytkownika lub agenta użytkownika, aby agent użytkownika mógł wyświetlić pomiar, aby użytkownik przestał ponawiać próbę i obsługiwał tylko kontakty. Z drugiej strony, jeśli ten interfejs API jest przeznaczony tylko dla systemów,

użytkownik90766
źródło
404 naprawdę mówi, że „tego nie ma, a nie wiem, gdzie to jest”. 3xx i 5xx są w porządku, aby spróbować ponownie. Ale 4xx mówi: „twoje obecne zapytanie było dla mnie niewystarczające, aby znaleźć dla ciebie antyhing. Proszę, odejdź”.
Podoba mi się możliwość rozróżnienia adresu URL NIE ZNALEZIONEGO i zasobu NIE ZNALEZIONEGO ... Tak więc punkt końcowy usługi działa i działa 200, jednak żądany zasób NIE ZNALEZIONO 404 (Body odpowiedzi).
Lemoniada