Pracuję z interfejsem API REST, który znajduje się na serwerze, który obsługuje dane dla wielu urządzeń IoT.
Moim zadaniem jest wysłanie zapytania do serwera za pomocą interfejsu API w celu zebrania określonych informacji o wydajności tych urządzeń.
W jednym przypadku uzyskuję listę dostępnych urządzeń i odpowiadających im identyfikatorów, a następnie pytam serwer o więcej szczegółów przy użyciu tych identyfikatorów (GUID).
Serwer zwraca 500 Internal Server Error
zapytanie dotyczące jednego z tych identyfikatorów. W mojej aplikacji zgłaszany jest wyjątek i nie widzę szczegółów dotyczących błędu. Jeśli przyjrzę się dokładniej odpowiedzi Postmana , widzę, że serwer zwrócił JSON w treści zawierającej:
errorMessage: "This ID does not exist"
.
Pomiń fakt, że serwer podał identyfikator na początek - to osobny problem dla programisty.
Czy interfejs API REST powinien zwrócić a, 500 Internal Server Error
aby zgłosić, że zapytanie odwołuje się do obiektu, który nie istnieje? Moim zdaniem kody odpowiedzi HTTP powinny odnosić się ściśle do statusu wywołania REST, a nie do wewnętrznej mechaniki API. Spodziewałbym się 200 OK
odpowiedzi zawierającej błąd i opis, która byłaby zastrzeżona dla danego interfejsu API.
Przyszło mi do głowy, że istnieje potencjalna różnica w oczekiwaniu w zależności od struktury wywołania REST.
Rozważ te przykłady:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
W pierwszym przypadku identyfikator urządzenia jest przekazywany jako zmienna GET. Wartość 404 lub 500 wskazuje, że ścieżka ( /restapi/deviceinfo
) nie została znaleziona lub spowodowała błąd serwera.
W drugim przypadku identyfikator urządzenia jest częścią adresu URL. Lepiej zrozumiałbym a 404 Not Found
, ale nadal mogę argumentować na podstawie tego, które części ścieżki są interpretowane jako zmienne kontra punkty końcowe.
źródło
Odpowiedzi:
Myślę, że odpowiedź 404 jest najlepszym dopasowaniem semantycznym tutaj, ponieważ zasób, który próbujesz znaleźć (reprezentowany przez identyfikator URI użyty do zapytania) nie został znaleziony. Zwrócenie ładunku błędu w treści jest rozsądne, ale nie wymagane.
Zgodnie z RFC 2616 definicja kodu statusu 404 to:
źródło
/questions
, to jest/questions/368213
. Ten punkt końcowy nie istnieje w twoim scenariuszu. Pomyśl o tym w ten sposób: jeśli wykonujesz GET na / foo / bar i nie ma paska, dlaczego odpowiedź powinna być inna, jeśli / foo istnieje, czy nie?How do you differentiate between a 404 meaning "the query returned no results" and a 404 meaning "the endpoint does not exist"?
- 400 złych wniosków .Użyję twoich przykładów.
Jeśli punkt końcowy zwraca tablicę json , najlepszym wyborem jest
200 OK
pusta tablica, jeśli nie znaleziono żadnego wyniku.Jeśli punkt końcowy jest przeznaczony do powrotu pojedynczy wynik , mój wybór będzie
404 NOT FOUND
, bo dla mnie, prawo składni dla tego rodzaju punktu końcowego wynosi:http://example.com/restapi/deviceinfo/123
. Zwykle używam parametru żądania tylko do filtrowania i gdy mój punkt końcowy zwraca tablicę.Myślę, że na to pytanie już tutaj udzielono odpowiedzi . POST lub GET, wydaje się lepszy wybór,
404 NOT FOUND
ponieważ123
nie znaleziono zasobu .W obu przypadkach nie widzę konieczności wyjaśnienia powodu, dla którego prośba nie została ukończona. Informacje o żądaniu i kod HTTP już wyjaśniają, dlaczego.
źródło
/itms/1234
lub/items/12234
.HTTP 404
jest poprawny, ponieważ serwer rozumie, o jaki zasób żąda klient, ale nie ma tego zasobu.Kluczem jest fakt, że pracujesz z „REST API”. Interfejs API powinien zachowywać się tak, jakby wykonywał REpresentational State Transfer, a nie wykonywał funkcji. (Oczywiście termin „REST” ma szersze znaczenie, ale nadal można użyć jego dosłownego znaczenia w celu uzyskania dobrego efektu.) Klient zapytał o stan zasobu opisanego przez adres URL
http://example.com/restapi/device/123/info
. Querystring (/deviceinfo?id=123
) nie zmieniłby sytuacji. Serwer wie, że chcesz przenieść stan urządzenia 123, ale nie rozpoznaje tego jako znanego zasobu. StądHTTP 404
.Inne możliwe odpowiedzi omówione tutaj mają również określone znaczenie:
HTTP 200
- Mamy dla ciebie stan; jest w ciele odpowiedzi.HTTP 204
- Mamy dla ciebie stan; jest puste.HTTP 400
- Nie możemy powiedzieć, o jakie zasoby pytasz. Napraw swój adres URL.HTTP 500
- Awarie. Nie twoja wina.Patrz RFC 2616 Sec. 10 odpowiednio.
źródło
Błąd 5xx jest zwykle używany do wskazania, że serwer napotkał błąd i nie może ukończyć żądania. Jeśli serwer przyjmuje żądanie, może je pomyślnie przeanalizować, a następnie wykonuje swoją pracę, nie powinno to zwracać błędu 5xx.
Nie jestem pewien, czy istnieje jakakolwiek konwencja dotycząca zwrotu, jeśli zapytanie nie przyniesie rezultatów. Widziałem zarówno to, co opisujesz (200 z ciałem zawierającym komunikat), jak i 404 wskazujące, że nie znaleziono wyników. 200 najprawdopodobniej ma sens - żądanie zostało pomyślnie zakończone i nie wystąpiły problemy z żądaniem klienta lub podczas przetwarzania żądania przez serwer. Ciało może dostarczyć wiadomość do klienta.
Traktowałbym oba twoje przykłady (
http://example.com/restapi/deviceinfo?id=123
ihttp://example.com/restapi/device/123/info
) tak samo -123
jest to parametr. Oba przypadki to różne sposoby konstruowania żądania uzyskania informacji o urządzeniu dla urządzenia o identyfikatorze 123.Po pierwsze, rozważę autoryzację i uwierzytelnienie. Jeśli użytkownik nie ma odpowiednich uprawnień, zwrócę odpowiednio 403 lub 401. Chociaż nazywa się to „Nieautoryzowane”, rozumiem, że 401 dotyczy bardziej uwierzytelniania, a 403 - nieautoryzowanego lub odmowy zgody. Nie byłbym jednak zbyt wybredny, jeśli chcesz trzymać się 403 za wszystkie błędy uwierzytelnienia i autoryzacji.
Następnie poradziłbym sobie z tym identyfikatorem. Na podstawie Twojego przykładu wygląda to na identyfikator numeryczny. Jeśli podano wartość nienumeryczną, zwróciłbym wartość 400. Jeśli parametr mógłby być prawdopodobnie prawidłowym identyfikatorem urządzenia, kontynuowałbym przetwarzanie. Gdyby istniały inne argumenty, zostałyby one również sprawdzone tutaj. Oczekiwałbym, że treść odpowiedzi będzie zawierać odpowiednie informacje o tym, dlaczego żądanie było złe.
Gdyby wszystkie parametry były prawidłowe, zacząłbym przetwarzać żądanie. Jeśli system lub jakakolwiek zależność (baza danych, usługa strony trzeciej, inna usługa wewnętrzna) jest niedostępna, zwrócę kod 5xx - 503 byłoby specyficzne, ale 500 również byłoby dopuszczalne. W obu przypadkach zwróciłbym ciało z dodatkowymi szczegółami. Weź pod uwagę, że jeśli zewnętrzna zależność zgłasza limit czasu żądania 408, zjadłbym to i zwrócił 500 klientowi, pozwalając klientowi otrzymać 408 tylko wtedy, gdy upłynął limit czasu żądania. Jeśli system jest w stanie zrealizować żądanie, zwrócę 200 i odpowiedni organ.
204 może być przydatny w niektórych przypadkach, ale uniemożliwia wysłanie odpowiedzi. Zwłaszcza w ustawieniach API wysyłanie treści odpowiedzi z informacjami, które można wprowadzić do mechanizmu rejestrowania lub raportowania, wydaje się w większości przypadków właściwą decyzją.
Jedyny czas, w którym 404 zostanie zwrócony, to jeśli serwer nie ma
/deviceinfo
punktu końcowego ani/device/:id/info
punktu końcowego.Nie uważam, że identyfikator, który nie został znaleziony, jest taki sam jak nie znaleziono zasobu. Zasób to informacje o urządzeniu dla określonego urządzenia (w twoim przykładzie). Zwrócenie wartości 404 oznaczałoby, że zasób (informacje o urządzeniu) nie istnieje. 200 z odpowiednim korpusem oznacza, że system rzeczywiście może dostarczyć informacje o urządzeniu. Może istnieć urządzenie o określonym identyfikatorze lub nie.
źródło
device: 123; status: not found;
. Wiem, że zapytanie zadziałało i że interfejs API przekazuje mi przydatne informacje.Błąd HTTP serii 500 oznacza awarię serwera. Oprócz
501 Not Implemented
i505 HTTP Version Not Supported
używanie tych kodów błędów niesie ze sobą implikację, że ponawianie żądania w późniejszym czasie może się powieść (chociaż503 Service Unavailable
wyraźnie to zaznacza). Idealnie byłoby, gdyby serwer nigdy nie produkował żadnego z tych kodów, chociaż niemożność napisania oprogramowania wolnego od błędów i zapewnienia serwerowi nieskończonych zasobów oznacza, że będziesz go potrzebował od czasu do czasu.W przypadku wyniku „obiekt nie istnieje” powinieneś prawdopodobnie zwrócić albo
404 Not Found
(gdy żądanie dotyczy obiektu według nazwy), albo200 Success
z pustą treścią wyniku (podczas wyszukiwania obiektu według atrybutów).204 No Content
wygląda kusząco, ale użyłbym tego tylko w sytuacjach, w których brak odpowiedzi jest oczekiwanym rezultatem.źródło
Jako klient interfejsu API, kiedy wykonuję jedno z tych wywołań:
http://example.com/restapi/deviceinfo?id=123
http://example.com/restapi/device/123/info
Oczekuję, że odzyskam (reprezentację)
DeviceInfo
obiektu (lub jakiegoś konkretnego typu, niezależnie od tego, czy jest to typ formalny, czy po prostu coś zgodnego z udokumentowaną konwencją typu „kaczego”). Chcę200
status oznacza, że faktycznie dostał jeden, i mogę śmiało używać.W przypadku interfejsów API REST uważam kody statusu 400 i 500 za coś w rodzaju wyjątków. Używasz ich, aby wskazać, kiedy nie możesz zwrócić „normalnej” odpowiedzi na otrzymane żądanie, więc klient będzie musiał zrobić coś wyjątkowego, a nie przetworzyć informacje, które spodziewał się uzyskać.
Oznacza to, jako konsument interfejsu API, że mogę skorzystać z funkcji sprawdzania-rest-call, która pobiera odpowiedź lub zgłasza wyjątek. To wspaniale; moją normalną logiką może być kod linii prostej i mogę zorganizować obsługę błędów w taki sam sposób, jak robię to w kodzie lokalnym. Nieoczekiwane 404 pojawią się jako wyjątki „nie znaleziono zasobu”, bez konieczności robienia czegokolwiek, a nie jako błędy „brakującego atrybutu”, kiedy przetwarzam później,
{ errorMessage: "Device 123 not found" }
jakby to byłDeviceInfo
obiekt.Jeśli uważasz, że punkt końcowy
http://example.com/restapi/deviceinfo
został znaleziony, a to tylko to,id=123
czego nie ma, a więc zwróć 200 z komunikatem o błędzie w ciele, to tworzysz dokładnie taki sam rodzaj problemów z interfejsem jak funkcje C, które mogą zwrócić albo poprawny wynik lub kod błędu lub metody wskazujące problemy przez arbitralne zwracanienull
. O wiele przyjemniej jest dla użytkownika interfejsu wyświetlać błędy przez „oddzielny” kanał od regularnych zwrotów. Dotyczy to również tutaj, mimo że odpowiedzi HTTP 200, 404 i 500 są tym samym kanałem z niskiego poziomu widzenia. Są one znormalizowane i łatwe do odróżnienia, dzięki czemu moja platforma klienta REST może łatwo włączyć te statusy, aby przekształcić je we właściwe struktury w moim języku; aby zrobić to samo z warstwą JSON (gdzie zawsze mówisz 200 iDeviceInfo
wyświetlasz komunikat o błędzie lub błąd), muszę zagłębić się w wiedzę na temat używanych przez Ciebie schematów JSON.Używaj więc 200 tylko wtedy, gdy możesz zwrócić poprawną wartość oczekiwanego typu (dlatego
http://example.com/restapi/search-devices?colour=blue
możesz zwrócić 200 z pustą tablicą, jeśli nie ma niebieskich urządzeń; pusta tablica jest prawidłową tablicą i rozsądną odpowiedzią na żądanie „I chciałby poznać szczegóły wszystkich niebieskich urządzeń ”). Jeśli nie możesz, użyj najbardziej odpowiedniego kodu stanu innego niż 200. Mimo że „urządzenie 123 nie istnieje” jest prawidłową odpowiedzią na „podaj mi szczegóły dotyczące urządzenia 123” i nie jest błędem dla serwera , jest to wyjątek dla oczekiwań klienta, że otrzymają zwrotDeviceInfo
i powinien nie komunikować się normalnie „oto, o co prosiłeś”.źródło
Możesz użyć błędu 422 Nieprzetworzona jednostka, aby odróżnić od 404 nie znaleziono . 422 oznacza, że serwer rozumie żądanie, ale nie może udzielić właściwej odpowiedzi. Używam tego kodu w podobnych sytuacjach.
źródło
Błąd 500 zwykle wskazuje, że żądanie spowodowało awarię programu po stronie serwera; w środowiskach korporacyjnych błędy te są traktowane jak jajko w twarz i są unikane.
Błąd 4xx powinien zasygnalizować programiście, że punkt końcowy interfejsu API (zasób) nie istnieje. W konsekwencji, po osiągnięciu odpowiedniego punktu końcowego, każda obsługa błędów od tego momentu jest odpowiedzialnością programisty API, którą należy traktować z wdziękiem, tj. Z komunikatem o błędzie 200 odpowiedzi.
źródło
Chociaż w3 zauważa, że 404 jest używane, gdy żadna inna odpowiedź nie ma zastosowania , czy nie do tego jest odpowiednia odpowiedź 204 (bez zawartości)? Żądanie było prawidłowe z punktu widzenia przetwarzania, a serwer przetworzył je i ma wynik. To sukces, który skłania się do odpowiedzi 2xx. Nie było treści dla tego konkretnego żądania, więc 204 mówi użytkownikowi, że nie było nic złego w jego zapytaniu, ale nic tam nie ma.
Możesz również przedstawić słabą argument, że 409 (Konflikt) jest odpowiednią reakcją. Chociaż 409 jest najczęściej używane do testu POST, mówi się
prawdopodobnie nieistnienie żądanego identyfikatora jest tutaj konfliktem, a zwrócenie w komunikacie, że taki identyfikator nie istnieje w systemie, jest wystarczającą informacją dla użytkownika, aby rozpoznać i naprawić konflikt.
źródło
Pozostałe odpowiedzi to obejmują, ale chciałem tylko zauważyć, że błąd z serii 500 oznacza „popieprzyłem”. W tym przypadku „I” oznacza API, czyli nieobsługiwany błąd serwera lub podobny. Błąd serii 400 oznacza „zawiedliście” - wywołujący API wysłał coś niepoprawnego.
źródło
Inni użytkownicy udzielili prawidłowych odpowiedzi na pytanie, co zrobić, jeśli chcesz przejść przez książkę.
Sugerowałbym jednak, abyście czytali zbyt dużo na ODPOCZYNEK i byliście absolutnie koszerni w stosunku do tego.
REST jest kapryśnym protokołem, ponieważ jeśli chcesz przejść przez książkę podczas jej używania, to zmusza zarówno klienta, jak i serwer do zbudowania, mając konkretną wiedzę o tym, że komunikują się przez REST, więc w zasadzie konkretny protokół komunikacyjny jest użyte nie można wyodrębnić.
Istnieje inne podejście: całkowicie unikaj RESTfulness i używaj go jako protokołu komunikacyjnego i nic więcej. Oznacza to, że jedyne odpowiedzi, które muszą zostać zwrócone to „HTTP 200 OK” i „HTTP 500 Internal Server Error”, ponieważ jeśli chodzi o protokół komunikacyjny, każda próba komunikacji może przynieść tylko dwa wyniki: albo żądanie zakończyło się powodzeniem dostarczone na serwer, czy nie.
To, co dzieje się po dostawie, nie jest sprawą protokołu komunikacyjnego. Tak więc, gdy serwer pomyślnie otrzyma żądanie i zacznie je przetwarzać, może wystąpić wiele błędów, ale są to błędy specyficzne dla aplikacji, które nie są przedmiotem działalności protokołu komunikacyjnego. Powinny być one przekazywane w ramach odpowiedzi, która wygląda doskonale pomyślnie, o ile protokół komunikacyjny wie.
Podsumowując, polecam zwrócenie „HTTP 200 OK”, aw ramach ładunku odpowiedzi („treść treści odpowiedzi” w języku HTTP) występuje specyficzny dla aplikacji kod błędu, który mówi „Nie znaleziono identyfikatora” lub cokolwiek innego.
źródło