Jakiego czasownika HTTP należy użyć, aby wywołać akcję w usłudze sieciowej REST?

80

Wdrażam usługę internetową RESTful i jednym z dostępnych działań będzie reload. Będzie używany do przeładowywania konfiguracji, pamięci podręcznej itp.

Zaczęliśmy od prostego GETdo takiego identyfikatora URI: ${path}/cache/reload(nie przekazano żadnych parametrów, wywoływany jest tylko identyfikator URI). Wiem, że danych nie należy modyfikować za pomocą żądania GET.

Którego czasownika należy użyć, aby wywołać akcję / polecenie w usłudze RESTful?

Przeładowanie to polecenie usługi internetowej REST, które przeładowuje własną pamięć podręczną / konfigurację / itp. Nie jest to metoda zwracająca informacje do klienta.

Prawdopodobnie to, co próbuję zrobić, nie jest REST, ale nadal jest to coś, co należy zrobić w ten sposób. reloadMetoda była tylko prawdziwy przykład, który ma sens w zakresie stosowania i większość odpowiedzi koncentruje się na tym, ale w rzeczywistości, po prostu potrzebne, aby wiedzieć, które czasownik aby wywołać akcję, która nie robi CRUD, ale wciąż zmienia dane / stan.

Znalazłem ten szczegółowy asnwer na przepełnieniu stosu na temat: https://stackoverflow.com/questions/16877968/

Renato Dinhani
źródło
1
„Przeładowanie” to sens aplikacji odświeżającej dane, które będą wyświetlane? Czy jest jakaś różnica między ponownym załadowaniem a ponownym pobraniem danych?
Sean Redmond
1
@SeanRedmond Nie, dane nie są wysyłane do klienta. W rzeczywistości klient mówi do usługi sieci Web REST, aby wykonać polecenie wewnętrzne (przeładować). Coś w stylu: „wiele konfiguracji zostało zmienionych w bazie danych, więc usługa REST, załaduj je teraz do pamięci”.
Renato Dinhani,
Duplikat między witrynami: stackoverflow.com/q/15340946/319403
cHao
Czy rozważałeś użycie parametru nagłówka przy odpowiednich żądaniach? To brzmi jak odświeżenie pamięci podręcznej ...
Guran

Odpowiedzi:

25

Nie sądzę, aby istniał odpowiedni czasownik dla tej akcji, ponieważ ta transakcja nie jest tak naprawdę „ODPOCZNA”. „S” i „t” oznaczają „transfer stanu” i nic tu nie jest przekazywane. Lub, inaczej mówiąc, według najściślejszej definicji czasowniki takie jak PUT i POST są zawsze używane z rzeczownikiem, a „przeładowanie” ma tylko czasownik.

To przeładowanie może nie być ODPOWIEDNIE, ale może być nadal przydatne, a ty po prostu wybierzesz sposób na to, aby żyć i wyjaśnić, że to niezwykłe. GET jest prawdopodobnie najprostszy. W komentarzach jest jednak sporo sceptycyzmu, więc powinieneś pomyśleć o tym, czy ta operacja przeładowania jest wymagana, ponieważ coś innego nie do końca działa tak, jak powinna.

Sean Redmond
źródło
Zgadzam się, że to nie jest RESTful, ale może być przydatne. Myślę, że powinieneś doradzić PUT, ponieważ jest to prawdopodobnie idempotentne, ale nie zerowe.
Aaron Greenwald
@Aaron, porównanie idempotent i nullimpotent jest dobre i dobre, ale jak określić, kiedy nie jest impotententne?
Craig,
@Craig to idempotent, jeśli wielokrotne uruchomienie ma taki sam efekt, jak jednorazowe uruchomienie. Jest nullipotentny, jeśli uruchomienie go raz lub wiele razy ma taki sam wpływ na serwer, jak uruchomienie go zero razy. en.wikipedia.org/wiki/Idempotence
Aaron Greenwald
5
@AaronGreenwald „notimpotent” [not-im-poht-nt] [not-im-pawr-tnt] - przymiotnik - 1. Gra słów, „ nieważne ”, antonim przymiotnika „ważne”. 2. Humor… ;-)
Craig
@Craig Całkowicie za tym tęskniłem :)
Aaron Greenwald
75

Jeśli chcesz być ODPOCZYNYWANY, nie myśl o czasowniku, aby wykonać akcję, pomyśl o stanie, w którym ma znajdować się zasób po tym, jak klient coś zrobi.

Korzystając z jednego z powyższych przykładów, masz kolejkę e-mail, która wysyła wiadomości e-mail. Chcesz, aby klient umieścił tę kolejkę e-mail w stanie wstrzymanym lub zatrzymanym lub coś w tym rodzaju.

Tak więc klient wprowadza nowy stan dla serwera dla tego zasobu. Może być tak prosty jak ten JSON

PUT http://myserver.com/services/email_service HTTP/1.1
Content-Type: text/json

{"status":"paused"}

Serwer wymyśli, jak przejść z obecnego stanu (powiedz „uruchomiony”) do „wstrzymanego” statusu / stanu.

Jeśli klient wykonuje GET na zasobie, powinien zwrócić stan, w którym się znajduje (powiedz „wstrzymany”).

Powodem, aby zrobić to w ten sposób i dlaczego REST może być tak potężny, jest pozostawienie HOW, aby dostać się do tego stanu na serwerze.

Klient mówi po prostu „W takim stanie powinieneś być teraz”, a serwer wymyśla, jak to osiągnąć. Może to być zwykła zmiana w bazie danych. Może to wymagać tysięcy działań. Klient nie dba o to i nie musi wiedzieć.

Możesz więc całkowicie przepisać / przeprojektować sposób, w jaki robi to serwer, a klient nie dba o to. Klient musi być świadomy różnych stanów (i ich reprezentacji) zasobu, a nie żadnych elementów wewnętrznych.

Cormac Mulhall
źródło
2
Według mnie jest to poprawna odpowiedź. Odświeżanie danych na serwerze nie jest operacją idempotentną i GETjest całkowicie nieodpowiednim czasownikiem. PUTjest najbardziej odpowiednim czasownikiem, ponieważ operację można uważać za aktualizację „statusu ponownego załadowania” pamięci podręcznej do „przeładowanego”.
Jez
@Jez Z odpowiedzi tutaj, ja też wolę tę. Trzymając się metafory e-maila, od razu wydaje się dziwne, że myślisz o wysłaniu poczty, ustawiając ją w stan „wysyłania” zamiast po prostu wysyłając (działanie). Ale jeśli się nad tym zastanowić, to naprawdę to samo, co umieszczenie go w „skrzynce nadawczej”. W rzeczywistości sam system pocztowy prawdopodobnie umieszcza go w kolejce wewnętrznie, gdy każesz mu wysłać. Interfejs API pozwala więc ustawić pocztę w stanie „wysyłania”, a interfejs API nie jest zobowiązany do wyjaśnienia się poza tym.
Craig
Tak więc, mówiąc dalej, jeśli nie chcesz, aby wiadomość była wysyłana, ustaw ją w stanie „zaplanowanym” z datą / godziną, w której powinna zostać opublikowana. Jeśli nie jest kompletny, umieszczasz go (lub domyślnie / domyślnie) w stanie „roboczym” itp.
Craig
... chociaż myślę, że wolę POST niż PUT w tym przypadku, ponieważ PUT ma być również idempotentny, ale POST nie podlega takim ograniczeniom.
Craig
1
Możesz to zrobić, ale ostatecznie próbuje wpasować kwadratowy kołek w okrągły otwór. Nie ma powodu, dla którego klient musiałby uruchomić serwer, aby „przeładować” cokolwiek, co jest po prostu złym projektem architektonicznym. Serwer może aktualizować swój stan wewnętrzny przy każdym połączeniu lub w ustalonym odstępie czasu. Poleganie na kliencie, który nakazuje serwerowi ponowne załadowanie czegoś niezależnego od jakiegokolwiek rzeczywistego żądania stanu zasobu, nie jest architekturą RESTful.
Cormac Mulhall,
32

Niektóre inne odpowiedzi, w tym ta zaakceptowana, zalecają użycie GET (choć niezbyt entuzjastycznie).

Nie zgadzam się.

Po pierwsze, wszystkie pozostałe, które mówią ci, że to nie jest idealne i nie tak naprawdę RESTful są poprawne. W odpowiednim scenariuszu RESTful manipulujesz zasobami na serwerze i dodajesz, aktualizujesz, usuwasz, przywracasz itp. Te zasoby. PUT powinien wysłać ładunek reprezentujący, jaki powinien być zasób po zakończeniu żądania, a POST powinien wysłać ładunek reprezentujący zasób, który ma zostać dodany do serwera. I GET powinien zwrócić zasób na serwerze.

Masz RPC (zdalne wywołanie procedury), które nie jest RESTful - chcesz zrobić coś na serwerze. Więc jeśli próbujesz utworzyć API RESTful, powinieneś ponownie rozważyć to, co robisz.

To powiedziawszy, czasami trzeba trochę nagiąć reguły. Zwłaszcza jeśli rozwijasz wewnętrzny interfejs API, który nie będzie udostępniany publicznie, możesz zdecydować, że kompromis jest tego wart.

Jeśli tak, poleciłbym PUT lub POST, w zależności od tego, czy RPC jest idempotentny, czy nie.

Mówimy ogólnie, że HTTP PUT mapuje na SQL UPDATE i że HTTP POST mapuje na SQL INSERT, ale nie jest to do końca prawdą. Czystszy sposób na stwierdzenie, że HTTP PUT powinien być idempotentny, a HTTP POST nie musi. Oznacza to, że możesz wywoływać to samo żądanie PUT tyle razy, ile chcesz, bez żadnych skutków ubocznych. Gdy raz go zadzwonisz, to nieszkodliwe, aby zadzwonić ponownie. Ale nie powinieneś wielokrotnie wywoływać żądań POST, chyba że masz na myśli - każdy POST ponownie zmienia dane na serwerze.

W twoim przypadku, jeśli potrzebujesz tej funkcji przeładowania, poleciłbym PUT, ponieważ brzmi to jak idempotent. Ale nadal zachęcam was do rozważenia, co inni powiedzieli o tym, że wcale tego nie potrzebuje.

Aaron Greenwald
źródło
6

POSTi PUTsą czasownikami HTTP używanymi do przesyłania jednostki na serwer WWW. Za PUTpomocą przesłanej encji jest (nowa) reprezentacja zasobu o podanym URI, która nie pasuje do tego, co chcesz. POSTjest dla tradycyjnego modułu obsługi formularzy, w którym encja jest danymi pomocniczymi dla zasobu, więc to jest zwycięzca. Jednostka zawierałaby polecenie lub akcję (np. „Akcja = przeładuj”).

To powiedziawszy, to polecenie prawdopodobnie nie powinno być ujawniane za pośrednictwem interfejsu REST. Wygląda na to, że pojawia się konieczność „przeładowania”, ponieważ dane można zmieniać za pomocą innego kanału (np. Systemu plików, klienta DB). Skrytki powinny być przezroczyste. Ponadto żądania HTTP powinny mieć charakter atomowy, nawet biorąc pod uwagę wiadomości wysyłane innymi kanałami. Oferowanie polecenia „przeładuj” dla ustawień konfiguracji wydaje się niepotrzebną złożonością; wymaganie jest kruche. Wystawianie „przeładowania” do czyszczenia po aktualizacji przez inny kanał jest brudne, ponieważ jeden kanał nie zawiera całej rozmowy. Zamiast tego rozważ jeden z:

  • dokonywanie aktualizacji całkowicie przez REST
  • udostępnianie poleceń dla drugiego kanału
  • automatyzacja działań

Niektóre z tych opcji mogą nie być wykonalne, w zależności od innych ograniczeń.

Zobacz także „ PUT vs POST w REST ”.

outis
źródło
Dziękuję Ci. Usunąłem „wewnętrzny” element edycji, ponieważ w rzeczywistości metoda „przeładuj” ma być publiczna. Chciałem tylko powiedzieć, że odnosi się do samej usługi internetowej. Myślę, że opublikowanie „akcji” byłoby dobrym podejściem.
Renato Dinhani,
@ RenatoDinhaniConceição: nawet bez „wewnętrznego” nadal pachnie. Może warto zadać nowe pytanie, czy projekt jest dobry.
poza
4

Argumentowałbym, dlaczego żądanie klienta musi wyraźnie wykonać połączenie, aby odświeżyć coś takiego. Wygląda na to, że powinna to być albo ukryta logika w bardziej typowej implementacji GET (np. Dane Pull, ale usługa odświeża dane przed ich pobraniem), lub przez inny wyzwalacz w backendie od klienta.

W końcu dane / konfiguracja musiałyby być aktualne tylko przy kolejnych połączeniach, więc bardziej skłaniałem się do leniwego kontra chętnego połączenia do odświeżenia danych. Oczywiście zakładam tutaj wiele, ale cofnę się o krok, aby ponownie ocenić konieczność tak wyraźnego i niezależnego połączenia.

Thomas Stringer
źródło
Spójrz na moją edycję. „reload” nie jest poleceniem zwracającym dane. Odnosi się do samej usługi internetowej REST. Ogólnie rzecz biorąc, moje pytanie dotyczy wyzwalania działań w usłudze sieciowej REST. Innym przykładem mogą być: email_queue/stop_sending_emails. Właśnie wydaje polecenie dla czegoś przy użyciu interfejsu RESTful.
Renato Dinhani,
5
Nadal się zgadzam. Wywołanie SIGHUP w procesie lokalnym ma sens, ponieważ komputer powinien ufać osobie zalogowanej lokalnie, która ma dostęp do tego sygnału. Ale dla bezpaństwowego protokołu dostępnego w Internecie? Być może usługa sieci Web powinna automatycznie przeładowywać się w razie potrzeby za pomocą sondowania lub monitorowania plików. To połączenie powinno być całkowicie niepotrzebne.
1
Zgadzam się. Rzeczy takie jak konfiguracja i buforowanie mają być przezroczyste dla klienta. Być może powinieneś podać nam bardziej konkretny opis sytuacji, w której zostanie wywołany Twój punkt końcowy.
Benjamin Hodgson
3

Dlaczego nie potraktować działania jak zasobu. Ponieważ więc chcesz zaktualizować pamięć podręczną, POST opublikujesz nową akcję w swoim systemie.

Dla purystów możesz mieć do tego dedykowane adresy URL. Pamiętaj, że możesz to rozszerzyć i zapisać rzeczywiste działania w bazie danych (lub dowolnym innym magazynie) z datą, statusem, użytkownikiem itp. Tylko moje przemyślenia tutaj.

Ogólna operacja ogólnosystemowa / akcje / {akcja}

Operacja specyficzna dla typu zasobu / akcji / {zasobu} / {akcji}

Operacja specyficzna dla zasobu / akcji / {zasób} / {id} / {akcja}

W twoim przypadku pamięć podręczna jest prawdopodobnie ogólnosystemowa / action / reload_cache

Isometriq
źródło
0

Jakiego czasownika HTTP należy użyć, aby wywołać akcję w usłudze sieciowej REST?

Rozważając szczegóły usługi REST, często warto rozważyć tę heurystykę: w jaki sposób zaimplementowałbyś to na stronie internetowej?

HTML może tylko natywnie opisywać żądania GET i POST. Możemy więc rozpocząć wyszukiwanie.

Jest GETodpowiedni? Aby odpowiedzieć na to pytanie, musimy pomyśleć o założeniach, które mogą przyjmować klienci i elementy pośrednie GET. Semantyka GETjest bezpieczna

klient nie żąda i nie oczekuje żadnej zmiany stanu na serwerze źródłowym w wyniku zastosowania bezpiecznej metody do zasobu docelowego. Podobnie nie należy oczekiwać, aby racjonalne stosowanie bezpiecznej metody spowodowało jakąkolwiek szkodę, utratę własności lub niezwykłe obciążenie serwera źródłowego.

W związku z tym implikuje to, że klienci i komponenty pośrednie mogą według własnego uznania wywoływać żądanie GET tak często, jak to konieczne, aby zaspokoić własne obawy. Pająki mogą POBIERAĆ zasoby w sposób bezkrytyczny w celu aktualizacji swoich indeksów. Pamięci podręczne mogą być pobierane wstępnie. W niewiarygodnej sieci utracone wiadomości można próbować tak często, jak to konieczne, aby zapewnić co najmniej jedną odpowiedź.

Będzie używany do przeładowywania konfiguracji, pamięci podręcznej itp.

Jeśli są to drogie rzeczy, być może nie chcesz, aby klienci wydawali te żądania według własnego uznania.

POSTz drugiej strony jest skutecznie nieograniczony - to znacznie zmniejsza założenia, które mogą przyjmować klienci generyczni. Nie dostajesz komponentów składających spekulacyjne żądania POST, ponieważ byłyby one do tego wadliwe - nic w standardzie nie mówi, że jest w porządku.

PUT, PATCH, DELETE... to niebezpieczne metody z bardziej szczegółowych niż semantyki POST; to, czy są one odpowiednie, zależy od modelu zasobów.

Ważnym pomysłem, o którym należy pamiętać, jest to, że metody HTTP należą do domeny dokumentów (zobacz przemówienie Jima Webbera w 2011 r. ), Efekty, które opisujesz, prawdopodobnie nie są częścią domeny dokumentów, ale zamiast tego wywoływane są skutki uboczne przy zmianie dokumentów . Daje to dużą swobodę w zakresie organizacji dokumentów w celu wykonania pracy.

VoiceOfUnreason
źródło