Tworzę interfejs API REST, ale napotkałem problem.
Wydaje się, że przyjętą praktyką w projektowaniu interfejsu API REST jest to, że jeśli żądany zasób nie istnieje, zwracany jest kod 404.
Jednak dla mnie powoduje to niepotrzebną dwuznaczność. HTTP 404 jest tradycyjnie kojarzony ze złym identyfikatorem URI. W efekcie mówimy „Albo trafiłeś we właściwe miejsce, ale ten konkretny zapis nie istnieje lub nie ma takiej lokalizacji w Internecie! Naprawdę nie jestem pewien, który…”
Rozważ następujący identyfikator URI:
http://mywebsite/api/user/13
Jeśli otrzymam 404, czy to dlatego, że Użytkownik 13 nie istnieje? A może dlatego, że mój adres URL powinien być:
http://mywebsite/restapi/user/13
W przeszłości zwracałem właśnie wynik NULL z HTTP 200 OK
kodem odpowiedzi, jeśli rekord nie istnieje. To proste i moim zdaniem bardzo czyste, nawet jeśli niekoniecznie jest to akceptowana praktyka. Ale czy jest na to lepszy sposób?
źródło
Odpowiedzi:
404 to tylko kod odpowiedzi HTTP. Ponadto możesz podać treść odpowiedzi i / lub inne nagłówki z bardziej znaczącym komunikatem o błędzie, który zobaczą programiści.
źródło
Użyj,
404
jeśli zasób nie istnieje. Nie wracaj200
z pustym ciałem.Jest to podobne do
undefined
pustego ciągu (np.""
) W programowaniu. Chociaż są bardzo podobne, na pewno jest różnica.404
oznacza, że nic nie istnieje przy tym URI (jak niezdefiniowana zmienna w programowaniu). Powrót200
z pustym ciałem oznacza, że coś tam istnieje i że coś jest teraz puste (jak pusty ciąg w programowaniu).404
nie oznacza, że był to „zły URI”. Istnieją specjalne kody HTTP przeznaczone do błędów URI (np414 Request-URI Too Long
.).źródło
String getName()
, która ma implementację takiego:return this.name == null ? "" : this.name
. To nie jest błędna, chyba że klient ma wiedzieć, żethis.name
jestnull
.Jak w większości rzeczy „to zależy”. Ale dla mnie, twoja praktyka nie jest zły i nie jest wbrew specyfikacji HTTP per se . Wyczyśćmy jednak kilka rzeczy.
Po pierwsze, identyfikatory URI powinny być nieprzejrzyste. Nawet jeśli nie są nieprzejrzyste dla ludzi, są nieprzezroczyste dla maszyn. Innymi słowy, różnica pomiędzy
http://mywebsite/api/user/13
,http://mywebsite/restapi/user/13
jest taka sama jak różnica międzyhttp://mywebsite/api/user/13
ihttp://mywebsite/api/user/14
nie znaczy to samo nie jest taki sam okres. Tak więc 404 byłoby całkowicie odpowiedniehttp://mywebsite/api/user/14
(jeśli nie ma takiego użytkownika), ale niekoniecznie jedyna odpowiednia odpowiedź.Możesz także zwrócić pustą odpowiedź 200 lub, bardziej precyzyjnie, odpowiedź 204 (bez zawartości). To przekazałoby klientowi coś jeszcze. Oznaczałoby to, że zasób zidentyfikowany przez
http://mywebsite/api/user/14
nie ma treści lub jest zasadniczo niczym. To znaczy, że nie jest taki zasób. Jednak niekoniecznie oznacza to, że twierdzisz, że jakiś użytkownik trwał w magazynie danych o identyfikatorze 14. To jest twoja prywatna sprawa, a nie klient zgłaszający żądanie. Jeśli więc ma sens modelowanie zasobów w ten sposób, śmiało.Przekazywanie klientom informacji wiąże się z pewnymi konsekwencjami w zakresie bezpieczeństwa, które ułatwiłyby im odgadnięcie prawdziwych identyfikatorów URI. Zwrócenie 200 za chybienie zamiast 404 może dać klientowi wskazówkę, że przynajmniej
http://mywebsite/api/user
część jest poprawna. Złośliwy klient może po prostu próbować różnych liczb całkowitych. Ale dla mnie złośliwy klient i tak byłby w stanie odgadnąć tęhttp://mywebsite/api/user
część. Lepszym rozwiązaniem byłoby użycie UUID. tzn.http://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66
jest lepszy niżhttp://mywebsite/api/user/14
. W ten sposób możesz użyć swojej techniki zwracania 200, nie zdradzając zbyt wiele.źródło
404 Not Found technicznie oznacza, że obecnie nie uri map do zasobu. W twoim przykładzie interpretuję żądanie,
http://mywebsite/api/user/13
które zwraca wartość 404, co oznacza, że ten adres URL nigdy nie został zmapowany na zasób. Dla klienta powinien to być koniec rozmowy.Aby rozwiać wątpliwości w niejednoznaczny sposób, możesz ulepszyć swój interfejs API, podając inne kody odpowiedzi. Załóżmy na przykład, że chcesz zezwolić klientom na wysyłanie żądań GET do adresu URL
http://mywebsite/api/user/13
, chcesz poinformować, że klienci powinni używać kanonicznego adresu URLhttp://mywebsite/restapi/user/13
. W takim przypadku możesz rozważyć wydanie stałego przekierowania, zwracając 301 Przeniesiono na stałe i podając kanoniczny adres URL w nagłówku lokalizacji odpowiedzi. Mówi to klientowi, że w przypadku przyszłych żądań powinien użyć kanonicznego adresu URL.źródło
Zasadniczo brzmi to tak, jakby odpowiedź mogła zależeć od tego, jak powstaje żądanie.
Jeśli żądany zasób stanowi część identyfikatora URI zgodnie z żądaniem,
http://mywebsite/restapi/user/13
a użytkownik 13 nie istnieje, wówczas 404 jest prawdopodobnie odpowiedni i intuicyjny, ponieważ identyfikator URI jest reprezentatywny dla nieistniejącego użytkownika / encji / dokumentu / itp. To samo dotyczy bezpieczniejszej techniki przy użyciu GUIDhttp://mywebsite/api/user/3dd5b770-79ea-11e1-b0c4-0800200c9a66
i powyższego argumentu api / restapi.Jeśli jednak żądany identyfikator zasobu został zawarty w nagłówku żądania [dołącz własny przykład] lub rzeczywiście w URI jako parametr, np.
http://mywebsite/restapi/user/?UID=13
Wtedy URI nadal byłby poprawny (ponieważ koncepcja USER kończy się whttp://mywebsite/restapi/user/
); i dlatego można oczekiwać, że odpowiedź będzie wynosić 200 (z odpowiednio szczegółowym komunikatem), ponieważ określony użytkownik znany jako 13 nie istnieje, ale identyfikator URI tak. W ten sposób mówimy, że identyfikator URI jest dobry, ale żądanie danych nie zawiera treści.Osobiście 200 nadal nie czuje się dobrze (chociaż wcześniej twierdziłem, że tak jest). Kod odpowiedzi 200 (bez pełnej odpowiedzi) może spowodować, że problem nie zostanie zbadany, gdy na przykład zostanie wysłany nieprawidłowy identyfikator.
Lepszym rozwiązaniem byłoby wysłanie
204 - No Content
odpowiedzi. Jest to zgodne z opisem w3c * Serwer spełnił żądanie, ale nie musi zwracać ciała-jednostki, i może chcieć zwrócić zaktualizowaną metainformację. * 1 Zamieszanie, moim zdaniem, jest spowodowane wpisem w Wikipedii z informacją 204 Brak treści - Serwer pomyślnie przetworzył żądanie, ale nie zwraca żadnej treści. Zwykle używany jako odpowiedź na pomyślne żądanie usunięcia .Ostatnie zdanie jest wysoce dyskusyjne. Rozważ sytuację bez tego zdania, a rozwiązanie jest łatwe - po prostu wyślij 204, jeśli jednostka nie istnieje. Istnieje nawet argument za zwróceniem 204 zamiast 404, żądanie zostało przetworzone i żadna treść nie została zwrócona! Pamiętaj jednak, że 204 nie pozwalają na treść w treści odpowiedziŹródła
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes 1. http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
źródło
To bardzo stary post, ale napotkałem podobny problem i chciałbym podzielić się z wami moimi doświadczeniami.
Buduję architekturę mikrousług z pozostałymi interfejsami API. Mam niektóre usługi GET odpoczynku, zbierają dane z systemu zaplecza na podstawie parametrów żądania.
Postępowałem zgodnie z pozostałymi dokumentami projektowymi API i odesłałem HTTP 404 z doskonałym komunikatem o błędzie JSON do klienta, gdy nie było danych, które pasowałyby do warunków zapytania (na przykład wybrano rekord zero).
Gdy nie było żadnych danych do wysłania z powrotem do klienta, przygotowałem doskonały komunikat JSON z wewnętrznym kodem błędu itp., Aby poinformować klienta o przyczynie „Nie znaleziono”, i został on odesłany z powrotem do klienta z HTTP 404. działa w porządku.
Później utworzyłem klasę spoczynkowego interfejsu API, która jest łatwym pomocnikiem do ukrycia kodu związanego z komunikacją HTTP i korzystałem z tego pomocnika przez cały czas, gdy dzwoniłem do pozostałych interfejsów API z mojego kodu.
ALE musiałem pisać mylący dodatkowy kod tylko dlatego, że HTTP 404 miał dwie różne funkcje:
Ważne: mój moduł obsługi błędów spoczynkowego interfejsu API przechwytuje wszystkie wyjątki pojawiające się w usłudze zaplecza, co oznacza, że w przypadku każdego błędu mój spoczynkowy interfejs API zawsze zwraca doskonały komunikat JSON ze szczegółami komunikatu.
To jest pierwsza wersja metody pomocniczej mojego klienta, która obsługuje dwie różne odpowiedzi HTTP 404:
ALE , ponieważ mój klient Java lub JavaScript może odbierać dwa rodzaje HTTP 404, muszę jakoś sprawdzić treść odpowiedzi w przypadku HTTP 404. Jeśli mogę przeanalizować treść odpowiedzi, to jestem pewien, że otrzymałem odpowiedź tam, gdzie była brak danych do odesłania do klienta.
Jeśli nie jestem w stanie przeanalizować odpowiedzi, oznacza to, że odzyskałem prawdziwy HTTP 404 z serwera WWW (nie z pozostałej aplikacji API).
Jest to tak mylące, że aplikacja kliencka musi zawsze wykonać dodatkowe parsowanie, aby sprawdzić prawdziwy powód HTTP 404.
Szczerze mówiąc nie podoba mi się to rozwiązanie. Jest to mylące, musi cały czas dodawać klientom dodatkowe bzdury.
Zamiast więc używać HTTP 404 w tych dwóch różnych scenariuszach, zdecydowałem, że wykonam następujące czynności:
W takim przypadku kod klienta może być bardziej elegancki:
Myślę, że to lepiej radzi sobie z tym problemem.
Jeśli masz jakieś lepsze rozwiązanie, udostępnij je nam.
źródło
Ten stary, ale doskonały artykuł… http://www.infoq.com/articles/webber-rest-workflow mówi o tym ...
404 Nie znaleziono - usługa jest zbyt leniwa (lub bezpieczna), aby dać nam prawdziwy powód niepowodzenia naszej prośby, ale bez względu na powód musimy sobie z tym poradzić.
źródło
Uniform Resource Identifier to unikalny wskaźnik do zasobu. Źle sformatowany identyfikator URI nie wskazuje zasobu, dlatego wykonanie GET na nim nie zwróci zasobu. 404 oznacza, że serwer nie znalazł niczego pasującego do URI żądania. Jeśli podasz niewłaściwy lub zły identyfikator URI, to jest to twój problem i powód, dla którego nie dotarłeś do zasobu, czy to strony HTML, czy IMG.
źródło
W tym scenariuszu HTTP 404 jest kodem odpowiedzi dla interfejsu API REST, takim jak jednostka nieprzetworzona 400, 401, 404, 422
użyj obsługi wyjątków, aby sprawdzić pełny komunikat wyjątku.
Ten blok wyjątków zapewnia właściwy komunikat generowany przez interfejs API REST
źródło