Jak wybrać kod stanu HTTP w REST API dla „Jeszcze nie gotowy, spróbuj ponownie później”? [Zamknięte]

152

Rozwijam RESTful API, w którym http://server/thingyapi/thingyblob/1234zwraca plik (aka „blob”) powiązany z thingy # 1234 do pobrania. Może się jednak zdarzyć, że żądanie zostało wysłane w momencie, gdy plik nie istnieje na serwerze, ale z pewnością będzie dostępny w późniejszym czasie. Na serwerze jest proces wsadowy, który generuje wszystkie obiekty blob dla wszystkich rzeczy. Thingy 1234 już istnieje, a jego dane, inne niż blob, są już dostępne. Serwer nie musi jeszcze generować dziwnego bloba 1234.

Nie chcę zwracać 404; to dla rzeczy, które nie istnieją. To coś, co istnieje, ale jego obiekt blob nie został jeszcze wygenerowany. Coś jak film w YouTube, który jest „przetwarzany”. Nie sądzę, aby kody przekierowań były właściwe; nie ma „innego” adresu URL do wypróbowania.

Jaki jest prawidłowy kod stanu HTTP do zwrócenia w takim przypadku?

JCCyC
źródło
3
Nieco powiązane
Rob Hruska
7
Po pierwsze, jeśli rzecz 1234 nie ma jeszcze żadnej reprezentacji zdolnej do GET, w jakim sensie istnieje jako zasób (z punktu widzenia klienta)? Fakt, że wewnątrz serwera istnieje zadanie w kolejce do utworzenia 1234, nie wydaje się sugerować, że zasób 1234 istnieje. Po drugie, skąd klient uzyskał identyfikator URI ... / thingyblob / 1234? Serwer prawdopodobnie nie powinien był udostępniać tego identyfikatora URI klientowi, dopóki zasób nie był faktycznie w stanie GET.
Andy Dennie
1
Rzecz ma inne właściwości, które warto zdobyć, inne niż kropelka. To tylko kropla, której wygenerowanie zajmuje trochę czasu. Klient dostaje je np. Przez server / thingyapi / thingy / 1234
JCCyC
10
Standard HTTP zawiera wskazówki dotyczące kodów stanu, których należy używać w określonych sytuacjach. W związku z tym kwestia ta nie jest tak naprawdę oparta głównie na opinii .
Raedwald
2
A co z 204„Brak treści”? Is wskazuje, że serwer pomyślnie przetworzył żądanie i nie zwraca żadnej treści [w tej chwili].
Timo

Odpowiedzi:

77

Proponuję 202 - Accepted. Z dokumentacji :

Żądanie zostało przyjęte do realizacji, ale przetwarzanie nie zostało zakończone. [...] Jego celem jest umożliwienie serwerowi przyjęcia żądania dla innego procesu (być może proces zorientowany wsadowo, który jest uruchamiany tylko raz dziennie)

matsev
źródło
62
-1: Miałoby to sens dla żądania, które inicjuje proces, który ostatecznie tworzy „thingy # 1234”, ale nie dla żądania GET wydanego później dla samego „thingy # 1234”. W szczególności, 202 sugeruje, że w wyniku żądania GET, usługa wyśle ​​dane dla „thingy # 1234” w późniejszym czasie. To po prostu nie jest poprawne.
Sam Harwell,
7
Mówi się również: „Jednostka zwrócona z tą odpowiedzią POWINNA zawierać wskazanie bieżącego statusu żądania i albo wskaźnik do monitora stanu, albo oszacowanie, kiedy użytkownik może oczekiwać, że żądanie zostanie spełnione.”, Więc byłoby to dobry sposób, aby poinformować klienta, że ​​obiekt blob nie jest jeszcze gotowy, i sposób, aby dowiedzieć się, kiedy jest gotowy.
Remy Lebeau
3
Twierdzę, że „zaakceptowane do przetworzenia” oznacza, że ​​zapisujesz żądanie, aby można było je później wykonać. Jeśli jest po prostu ignorowany, należy zwrócić kod 4xx lub 5xx, aby wskazać klientowi, że może chcieć spróbować ponownie.
Łukasz
3
102 (przetwarzanie) wydaje się czasem rozsądnym wyborem, mimo że jest w specyfikacji webdav.
akostadinov
2
Nie mogę się bardziej nie zgodzić z tą odpowiedzią. Serwer nic nie zwraca lub nie planuje (nie wykonuje żadnego przetwarzania z powodu tego żądania - czego i tak nie powinien w przypadku GET). W związku z tym zasób jest w pewien sposób niedostępny dla klienta. Należy to traktować jako błąd, więc żaden kod 2XX nie jest odpowiedni. Coś w przestrzeni 4XX lub 5XX. Żądanie nie zostało „przyjęte do przetworzenia” , w praktyce wniosek jest odrzucany
Adam
52

Taki „problem” występuje po stronie serwera: klient wysłał dobrze sformułowane żądanie, ale serwer nie może go spełnić. Więc jestem skłonny do "Błąd serwera", kod statusu 5xx.

Quoth RFC 7231 (aktualny standard HTTP, podkreślenie dodane):

Klasa kodu stanu 5xx (Błąd serwera) wskazuje, że serwer jest świadomy tego, że popełnił błąd lub nie jest w stanie wykonać żądanej metody . Z wyjątkiem odpowiedzi na żądanie HEAD, serwer POWINIEN wysłać reprezentację zawierającą wyjaśnienie sytuacji błędu oraz czy jest to stan tymczasowy czy trwały.

Uwaga

  • „popełnił błąd lub nie jest w stanie wykonać żądania”: pomimo ich tytułu „Błąd serwera” nie dotyczą one tylko błędów serwera.
  • tymczasowe lub stałe”: te kody są odpowiednie dla tymczasowo niedostępnych zasobów, takich jak Twój.

Z dostępnych kodów najlepiej pasowałbym , że 503 „Usługa niedostępna” :

Kod stanu 503 (Usługa niedostępna) wskazuje, że 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.

Uwaga:

  • „prawdopodobnie zostanie złagodzony po pewnym czasie”: prawdziwe w Twoim przypadku.
  • „chwilowe przeciążenie”: nie jest pedantycznie prawdziwe w Twoim przypadku. Ale, można by się spierać, gdyby twój serwer był dużo szybszy, przetwarzanie wsadowe byłoby już wykonane, gdy klient wysyła żądanie, więc jest to rodzaj „przeciążenia”: klient prosi o zasoby szybciej niż serwer może wykonać są dostępne.
  • Ponowna próba jest odpowiednia dla Twojej usługi, więc Twoja odpowiedź powinna zawierać Retry-Afterwartość. Możesz podać jako wartość szacowany czas zakończenia następnego wykonania procesu wsadowego lub interwał wykonania procesu wsadowego.

Zdefiniowanie własnego kodu statusu 5xx (na przykład 591), chociaż dozwolone , miałoby niewłaściwą semantykę:

klient MUSI zrozumieć klasę dowolnego kodu statusu, na co wskazuje pierwsza cyfra, i traktować nierozpoznany kod statusu jako równoważny z kodem statusu x00 tej klasy

Klienci traktowaliby Twój własny kod statusu jako 500, „wewnętrzny błąd serwera” , co nie byłoby właściwe.

Raedwald
źródło
2
Nie widzę, jak to jest lepsze niż 202: benramsey.com/blog/2008/04/ ...
JCCyC
4
@JCCyC Twój blog to dobry argument za zwróceniem 202 w odpowiedzi na żądanie utworzenia czegoś (POST lub PUT). Wydaje się, że pytanie dotyczy tego, co zwrócić za GET.
Raedwald,
@JCCyC to może być postrzegane jako inny odcień niegotowości: wyobraź sobie Ajax do tego zasobu, czy wolisz 202 jako status sukcesu, czy 503 jako status błędu? dzięki czemu możesz zobaczyć, które znaczenie preferujesz pośrednio w kontekście reakcji aplikacji na odpowiedź
rloth
podoba mi się również praktyczny aspekt „Ponów próbę”, który
pasuje do
1
Uwaga: „Ponów po” również można zastosować, 307 - TEMPORARY REDIRECTco jest dobre, jeśli chcesz zmusić stronę klienta do czekania w innym miejscu, podczas gdy zasoby są „gotowe”
rloth
28

Myślę, że 423 - Locked można wykorzystać do tego celu:

Kod stanu 423 (Zablokowany) oznacza, że ​​zasób źródłowy lub docelowy metody jest zablokowany. Ta odpowiedź POWINNA zawierać odpowiedni kod warunku wstępnego lub warunku końcowego, na przykład „przesłano token blokady” lub „blokada nie powodująca konfliktu”.

Fernando Ortega
źródło
1
Doskonała odpowiedź! Zastanawiam się, dlaczego nie ma więcej pozytywnych głosów.
lex82
10
Może dlatego, że jest to kod HTTP WebDAV?
Stephan L
1
Z akka-http jest StatusCode RetryWith = reg (c (449) ("Ponów próbę z", "Żądanie powinno zostać ponowione po wykonaniu odpowiedniej czynności.")), Gdzie akcja będzie czekać i ponowić próbę
ozma
2
Pod wieloma względami się z tym zgadzam. Mam podobną sytuację (w moim przypadku wyszukuję z indeksu, który może jeszcze nie być wypełniony). Myślę, że semantycznie to jest poprawne. Jednak dokument RFC dla 423 stwierdza: „Ta odpowiedź POWINNA zawierać odpowiedni kod warunku wstępnego lub warunku końcowego, taki jak„ przesłano token blokady ”lub„ blokada nie powodująca konfliktu ”. Nie wiem, jak to tutaj zastosować. Osobiście wybrałbym 409 Conflict, ale to zostało odrzucone bez komentarzy - nie wiesz, dlaczego?
Adam
22

Nie chcę zwracać 404; to dla rzeczy, które nie istnieją.

Adres URL nie odpowiada prośbie o coś.

http://server/thingyapi/thingyblob/1234

Klient prosi o coś, co nie istnieje. Gdyby istniał, oddałbyś go im.

404.

funroll
źródło
1
Cieszę się, że ktoś to powiedział! Nie mogę uwierzyć, że jest tak wielu ludzi, którzy uważają, że 503jest to odpowiednia odpowiedź. Nie wspominając o innych dziwnych sugestiach.
Jason Desrosiers
Chociaż zgadzam się, że 404 jest tutaj najbardziej odpowiednią odpowiedzią, nie odpowiada na pytanie OP, jak wskazać, kiedy coś jest dostępne :-). Myślę, że pole Ponów próbę po wydaje się najlepszym kandydatem, ale może być oficjalnie używane tylko w przypadku kodów 503 i 3xx. @Jason: Myślę, że to wyjaśnia niektóre dziwne sugestie.
Ron Deijkers,
Myślę, że to najlepsza odpowiedź. Możesz zwrócić treść w odpowiedzi 404. Ciało może wskazywać, że rzecz będzie dostępna w późniejszym terminie. Lub użyj również nagłówka Retry-After. Trzeba tu trochę naciągnąć standard, bo ten przypadek nie obejmuje ładnie.
WW.
4
Ludzie za bardzo przyzwyczaili się do 404, co oznacza, że ​​strona nie odkryła, że ​​nie może logicznie oddzielić tego w kontekście API.
The Muffin Man
1
To jest baaaardzo 404. Thingyblob jeszcze nie istnieje, ani nigdy .. Dla http nie ma znaczenia, czy kiedykolwiek będzie dostępny. W tej chwili nie istnieje, a jego 404. Kiedy będzie dostępny, jest inny problem, który można rozwiązać, wysyłając wiadomość z serwera do klienta, mówiącą, że dostępny jest thingyblob: 1234. Wykonaj jeszcze raz get i voila ..
100r
21

Inna opcja: 503 - Service Unavailable.

Brian Kelly
źródło
5
Według W3C to nie jest to, co chciałbyś powiedzieć klientowi (chociaż w jakiś sposób oznacza to „przyjdź ponownie”): „Serwer obecnie nie jest w stanie obsłużyć żądania z powodu tymczasowego przeciążenia lub konserwacji serwera. Implikacja jest taka, że jest to stan tymczasowy, który zostanie złagodzony po pewnym opóźnieniu. Jeśli jest znana, długość opóźnienia MOŻE być wskazana w nagłówku Retry-After. Jeśli nie podano Retry-After, klient POWINIEN obsłużyć odpowiedź tak, jak w przypadku 500 odpowiedzi ”.
skalee
4
Usługa nie jest niedostępna, usługa jest dostępna, ale przetwarzanie nie zostało zakończone. Więc 503 prawdopodobnie nie jest dobrym pomysłem.
Ishtiaque Khan
17

Ponieważ Twój zasób nie jest gotowy, prawdopodobnie wiesz, kiedy (w przybliżeniu) będzie dostępny i kiedy klient może ponowić żądanie. Oznacza to, że możesz chcieć użyć nagłówka Retry-After . Ten nagłówek jest prawidłowy z kodem 503 (Usługa niedostępna), co oznacza, że ​​cała witryna jest niedostępna z powodu konserwacji i odpowiedzi 3xx (przekierowanie).

Moim zdaniem 302 (Znaleziono) z nagłówkiem Retry-After byłoby najlepszą opcją, ale nie jestem pewien, czy pole Location nagłówka odpowiedzi może być równe adresowi żądania. W każdym razie to przekierowanie cykliczne.

skalee
źródło
3
Nawet jeśli jest to dozwolone, jeśli klient nie zaimplementował obsługi nagłówka Retry-After, przekierowanie 3xx na tę samą stronę może ostatecznie zakończyć się kodem 503 ... (opcjonalnie z oczywiście nagłówkiem Retry-After)
Ron Deijkers
1
Ponowna próba po jest również poprawna w przypadku protokołu HTTP 429 „Zbyt wiele żądań”, dodanego przez RFC 6585 (kwiecień 2012). Może to być właściwe, jeśli powodem, dla którego zasób nie jest jeszcze gotowy, jest to, że klient poświęcił serwerowi zbyt dużo pracy.
Silas S. Brown
8

409 Konflikt

Wskazuje, że żądanie nie mogło zostać przetworzone z powodu konfliktu w żądaniu, takiego jak konflikt edycji w przypadku wielu aktualizacji. [Źródło Wikipedia.]

To mogłoby być właściwe.

Jeśli nie możesz spełnić żądania, zwracając dane - to się nie powiedzie. Myślę, że 202 sugeruje, że serwer ustawił żądanie w kolejce i spełni żądanie później. Ale w twoim przypadku żądanie dotyczy teraz danych i nie powiodło się. Jeśli spróbujesz później, jest to inne żądanie.

Myślę, że masz konflikt… chcesz danych… ale są one edytowane / aktualizowane. Byłoby tak również w przypadku, gdyby Thingy1234 już istniał i został pomyślnie pobrany wcześniej, ale teraz był w trakcie edycji i był niedostępny podczas edycji.

J Moore
źródło
2
Nie jestem pewien, dlaczego to zostało odrzucone. Wydaje mi się, że to dobra odpowiedź. Z dokumentu RFC: „Kod stanu 409 (konflikt) wskazuje, że żądanie nie mogło zostać zakończone z powodu konfliktu z bieżącym stanem zasobu docelowego. Ten kod jest używany w sytuacjach, w których użytkownik może być w stanie rozwiązać konflikt i prześlij żądanie ponownie. ”Poprosiłeś o zasób, którego serwer nie może zwrócić, ponieważ serwer jest w trakcie aktualizacji tego zasobu - tj. z powodu aktualnego stanu zasobu. Klient może rozwiązać ten problem, czekając i przesyłając ponownie
Adam
1
@Adam Myślę, że wniosek „użytkownik może być w stanie rozwiązać konflikt” jest taki, że coś związanego z ponownym przesłaniem byłoby inne, niż tylko czekanie.
Holistic Developer
3

501 - Nie wdrożono

Dokładnie tak, jak to brzmi. Funkcja, która nie została jeszcze zaimplementowana, ale zakłada dostępność w przyszłości.

Oto link do podsumowania błędów 5xx .

Dan
źródło
4
W przypadku tego pytania wygląda na to, że sama funkcja istnieje, ale żądana pozycja nie.
Łukasz
Opis @Luke 501 z linku w mojej odpowiedzi: „... brakuje mu możliwości spełnienia żądania. Zwykle oznacza to dostępność w przyszłości ”. Jest to dokładnie to, o co prosił PO. Niezależnie od tego, czy dane znajdują się na jego serwerach lub w bazie danych. Ostatecznym rezultatem jest to, że na razie nie jest dostępny przez API. Dlatego API nie może spełnić żądania, ale chciałoby zasugerować, że będzie dostępne w przyszłości za pośrednictwem kodu http.
Dan,