Czy zwracanie 202 „Zaakceptowano” w odpowiedzi na HTTP GET jest błędem?

89

Mam zbiór zasobów, których reprezentacje są leniwie tworzone. Obliczenia potrzebne do zbudowania tych reprezentacji mogą zająć od kilku milisekund do kilku godzin, w zależności od obciążenia serwera, określonego zasobu i fazy księżyca.

Pierwsze żądanie GET odebrane dla zasobu rozpoczyna obliczenia na serwerze. Jeśli obliczenia zakończy się w ciągu kilku sekund, zwracana jest obliczona reprezentacja. W przeciwnym razie zwracany jest kod stanu 202 „Zaakceptowano”, a klient musi odpytywać zasób, aż ostateczna reprezentacja będzie dostępna.

Przyczyna tego zachowania jest następująca: Jeśli wynik jest dostępny w ciągu kilku sekund, należy go pobrać tak szybko, jak to możliwe; w przeciwnym razie, kiedy stanie się dostępny, nie jest ważne.

Ze względu na ograniczoną pamięć i ogromną liczbę żądań, ani NIO, ani długie odpytywanie nie są opcją ( tj. Nie mogę utrzymać prawie wystarczającej liczby otwartych połączeń, ani nawet nie mogę nawet zmieścić wszystkich żądań w pamięci; raz „kilka sekund” minęły, podtrzymuję nadmiar żądań). Podobnie ograniczenia klienta są takie, że nie mogą zamiast tego obsługiwać wywołania zwrotnego zakończenia. Na koniec zwróć uwagę, że nie jestem zainteresowany tworzeniem zasobu „fabrycznego”, do którego się POST wysyła, ponieważ dodatkowe podróże w obie strony oznaczają, że zawodzimy odcinkowe ograniczenie czasu rzeczywistego bardziej niż jest to pożądane (ponadto jest to dodatkowa złożoność; ponadto jest to zasób, który korzyści z buforowania).

Wyobrażam sobie, że istnieją pewne kontrowersje dotyczące zwracania kodu stanu 202 „Zaakceptowano” w odpowiedzi na żądanie GET, ponieważ nigdy nie widziałem tego w praktyce, a jego najbardziej intuicyjne użycie jest odpowiedzią na niebezpieczne metody, ale nigdy nie znalazł coś szczególnie zniechęcającego. Co więcej, czy nie zachowuję jednocześnie bezpieczeństwa i idempotencji?

Więc co ludzie myślą o tym podejściu?

EDYCJA : Powinienem wspomnieć, że dotyczy to tak zwanego biznesowego internetowego interfejsu API - nie dla przeglądarek.

user359996
źródło
2
Osobiście uważam, że jest dobry, to jest dokładnie definicja pliku 202. To, że jest rzadko używane w praktyce, jest bardziej IMHO, ponieważ niewielu programistów internetowych dba o prawidłowe kody statusu, ponieważ są bardziej przyzwyczajeni do interakcji przeglądarki / użytkownika-agenta, w którym to przypadku nie 202daje im widocznej wskazówki (daj im 200i są zadowoleni. ..).
Wrikken
1
@ user359996, po prostu użyj 200. 202jest tym, czym ma być, ale w praktyce ludzie się tego nie spodziewają 202.
Pacerier
potrzebuje jednak ETA, żeby 200 był użyteczny w praktyce.
Rob

Odpowiedzi:

66

Jeśli jest przeznaczony dla dobrze zdefiniowanego i udokumentowanego interfejsu API, 202brzmi dokładnie tak, jak to się dzieje.

Jeśli chodzi o publiczny Internet, martwiłbym się zbytnio o zgodność klienta. Widziałem tak wiele if (status == 200)zakodowanych na stałe ... W takim przypadku zwróciłbym plik 200.

Ponadto dokument RFC nie wskazuje, że użycie 202 dla żądania GET jest błędne, podczas gdy zawiera wyraźne rozróżnienia w innych opisach kodu (np. 200).

Żądanie zostało przyjęte do realizacji, ale przetwarzanie nie zostało zakończone.

Pekka
źródło
16

Zrobiliśmy to dla niedawnej aplikacji, klient (niestandardowa aplikacja, a nie przeglądarka) wysłał zapytanie POST i serwer zwrócił 202 z URI do wysyłanego "zadania" - klient użyłby tego URI do odpytania o wynik - wydaje się, że pasuje do tego, co zostało zrobione.

Najważniejsze jest tutaj udokumentowanie, jak działa twoja usługa / API i co oznacza odpowiedź 202.

nr
źródło
+1 Dzięki za komentarz. Dobra uwaga na temat dokumentacji. Proszę jednak zwrócić uwagę na wyjaśniające zmiany w moim pytaniu (szukaj hasła „fabryka”).
user359996
Cóż, możesz pominąć ten identyfikator URI w odpowiedzi, jeśli chcesz tylko odpytać ten sam URI, o który pierwotnie prosiłeś. (Po prostu udokumentuj, jak to powinno działać :-))
nr
Dobry pomysł, ale pamiętaj, że chcę buforować, więc nie ma POST. Ponadto identyfikator URI określa zasób, a nie metodę. Przyjmuję podejście RESTful, a nie RPC (przepraszam, kolejne nieokreślone ograniczenie - moja wina).
user359996
Dokładniej mówiąc, przez „RESTful” mam na myśli „zorientowany na zasoby”, który jest technicznie nieco większy niż jest to określone w ograniczeniach REST.
user359996
12

Z tego co pamiętam - GET ma zwrócić zasób bez modyfikowania serwera. Może aktywność zostanie zarejestrowana lub co masz, ale żądanie powinno być ponownie uruchomione z tym samym wynikiem.

POST z drugiej strony to żądanie zmiany stanu czegoś na serwerze. Wstaw rekord, usuń rekord, uruchom zadanie, coś w tym rodzaju. 202 byłby odpowiedni dla POST, który zwrócił, ale nie został ukończony, ale tak naprawdę nie jest żądaniem GET.

To wszystko jest bardzo purytańskie i niezbyt dobrze praktykowane w naturze, więc prawdopodobnie jesteś bezpieczny, zwracając 202. GET powinien zwrócić 200. POST może zwrócić 200, jeśli zakończyło się, lub 202, jeśli nie zostało wykonane.

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Dlongnecker
źródło
4
Bardzo dobre myślenie, ale nie jestem pewien, czy ma to zastosowanie tutaj: z tego, co mówi OP, wydaje się, że jest to właściwe żądanie GET (ponieważ nie zmienia niczego na serwerze), po prostu obliczenie zajmuje więcej czasu ten przypadek ma zostać pobrany w innym czasie. Może PO może przedstawić miarodajny komentarz. To dla API, więc dobrze jest być „purytaninem” ze względu na czysty interfejs
Pekka
Och, dotknij pekka. Masz rację, GET to droga do zrobienia. I nie sądzę, aby protokół HTTP SPC naprawdę wziął pod uwagę GET, które nie są gotowe. Więc mógł iść w obie strony
Dlongnecker
7
(Teraz nieistotny) autorytatywny komentarz: Tak, uważam to za idempotentne. Zasób nie jest ani modyfikowane ani stworzony, raczej jest to reprezentacja nie została jeszcze obliczona.
user359996
1
Gdzie to jest napisane? Ponadto, jeśli zwrócę 200, klient powinien oczekiwać zwrotu reprezentacji, ale tak się nie stało.
user359996
1
Cofam to. Wygląda na to, że 202 nie odpowiada tylko GET lub POST. Sam sposób myślenia, w jakim byłem, kiedy patrzyłem na protokół, sprawił, że 202 istniało tylko dla żądań GET. 202 powinno wystarczyć do twoich celów.
Dlongnecker
0

W przypadku zasobu, który ma mieć reprezentację podmiotu, który jest wyraźnie określony identyfikatorem (w przeciwieństwie do zasobu „fabrycznego”, jak opisano w pytaniu), zalecam pozostanie przy metodzie GET i sytuacji, gdy jednostka / reprezentacja jest niedostępna z powodu leniwego tworzenia lub jakiejkolwiek innej tymczasowej sytuacji, użyj kodu odpowiedzi 503 Niedostępna usługa, który jest bardziej odpowiedni i został faktycznie zaprojektowany na potrzeby takich sytuacji.

Powód tego można znaleźć w dokumentach RFC dotyczących samego protokołu HTTP (proszę sprawdzić opis kodu odpowiedzi 503), a także w wielu innych zasobach.

Porównaj z kodem stanu HTTP dla tymczasowo niedostępnych stron . Chociaż to pytanie dotyczy innego przypadku użycia, w rzeczywistości dotyczy dokładnie tej samej funkcji protokołu HTTP.

Hermes
źródło