Czy to REST API to naprawdę RPC? Roy Fielding wydaje się tak myśleć

99

Wiele z tego, co wydawało mi się, że wiem o REST, jest najwyraźniej błędne - i nie jestem sam. To pytanie ma długie wprowadzenie, ale wydaje się być konieczne, ponieważ informacje są nieco rozproszone. Właściwe pytanie kończy się, jeśli znasz już ten temat.

Od pierwszego akapitu interfejsów API REST Roya Fieldinga muszą być oparte na hipertekstach , jest całkiem jasne, że uważa, że ​​jego praca jest szeroko błędnie interpretowana:

Irytuje mnie liczba osób nazywających dowolny interfejs oparty na HTTP jako REST API. Dzisiejszym przykładem jest SocialSite REST API . To jest RPC. Krzyczy RPC. Na wyświetlaczu jest tak wiele sprzężeń, że należy mu przyznać ocenę X.

Następnie Fielding wymienia kilka atrybutów interfejsu API REST. Niektóre z nich wydają się być sprzeczne zarówno z powszechną praktyką, jak i popularnymi radami na SO i innych forach. Na przykład:

  • REST API należy wprowadzić bez wcześniejszej wiedzy poza początkowym identyfikatorem URI (zakładką) i zestawem standardowych typów mediów, które są odpowiednie dla zamierzonej grupy odbiorców (tj. Mają być zrozumiane przez każdego klienta, który może korzystać z API). ...

  • REST API nie może definiować stałych nazw zasobów ani hierarchii (oczywiste połączenie klienta i serwera). ...

  • REST API powinien poświęcić prawie cały swój opisowy wysiłek na zdefiniowanie typu (-ów) mediów używanych do reprezentowania zasobów i sterowania stanem aplikacji lub na definiowanie rozszerzonych nazw relacji i / lub znaczników z obsługą hipertekstu dla istniejących standardowych typów mediów. ...

Idea „hipertekstu” odgrywa kluczową rolę - znacznie bardziej niż struktura URI czy znaczenie czasowników HTTP. „Hipertekst” jest zdefiniowany w jednym z komentarzy:

Kiedy [Fielding] mówię hipertekst, mam na myśli równoczesną prezentację informacji i sterowanie w taki sposób, że informacja staje się afordancją, przez którą użytkownik (lub automat) uzyskuje wybory i wybiera działania. Hypermedia to tylko rozwinięcie tego, co tekst oznacza włączenie czasowych kotwic do strumienia mediów; większość badaczy zrezygnowała z tego rozróżnienia.

W przeglądarce hipertekst nie musi być kodem HTML. Maszyny mogą podążać za linkami, jeśli rozumieją format danych i typy relacji.

Zgaduję w tym miejscu, ale pierwsze dwa punkty powyżej wydają się sugerować, że dokumentacja API dla zasobu Foo, która wygląda jak poniżej, prowadzi do ścisłego sprzężenia między klientem a serwerem i nie ma miejsca w systemie RESTful.

GET   /foos/{id}  # read a Foo
POST  /foos/{id}  # create a Foo
PUT   /foos/{id}  # update a Foo

Zamiast tego agent powinien zostać zmuszony do znalezienia identyfikatorów URI dla wszystkich Foos, na przykład przez wysłanie żądania GET przeciwko / foos. (Te identyfikatory URI mogą być zgodne z powyższym wzorcem, ale to nie ma znaczenia). Odpowiedź wykorzystuje typ mediów, który jest w stanie przekazać, jak uzyskać dostęp do każdego elementu i co można z nim zrobić, co prowadzi do trzeciego punktu powyżej. . Z tego powodu dokumentacja API powinna koncentrować się na wyjaśnieniu sposobu interpretacji hipertekstu zawartego w odpowiedzi.

Ponadto za każdym razem, gdy żądany jest identyfikator URI do zasobu Foo, odpowiedź zawiera wszystkie informacje potrzebne agentowi do odkrycia, jak postępować, na przykład, uzyskując dostęp do powiązanych i nadrzędnych zasobów za pośrednictwem ich identyfikatorów URI lub podejmując działania po utworzeniu / usunięcie zasobu.

Kluczem do całego systemu jest to, że odpowiedź składa się z hipertekstu zawartego w typie nośnika, który sam przekazuje agentowi opcje postępowania. Nie różni się to od sposobu, w jaki przeglądarka działa dla ludzi.

Ale to tylko moje przypuszczenie w tym konkretnym momencie.

Fielding opublikował dalszy ciąg , w którym odpowiedział na krytykę, że jego dyskusja była zbyt abstrakcyjna, pozbawiona przykładów i bogata w żargon:

Inni będą próbowali rozszyfrować to, co napisałem, w sposób bardziej bezpośredni lub mający zastosowanie do niektórych praktycznych problemów dnia dzisiejszego. Pewnie nie, bo jestem zbyt zajęty zmaganiem się z kolejnym tematem, przygotowywaniem się do konferencji, pisaniem innego standardu, podróżowaniem w jakieś odległe miejsce lub po prostu robieniem drobiazgów, które pozwalają mi poczuć, że zarobiłem na wypłatę.

A więc dwa proste pytania do ekspertów REST z praktycznym nastawieniem: jak interpretujesz to, co mówi Fielding i jak wprowadzasz to w życie podczas dokumentowania / wdrażania interfejsów API REST?

Edycja: to pytanie jest przykładem tego, jak trudno jest się czegoś nauczyć, jeśli nie masz nazwy dla tego, o czym mówisz. W tym przypadku nazwa to „Hypermedia jako silnik stanu aplikacji” (HATEOAS).

Rich Apodaca
źródło
26
John, Rich właśnie wyjaśnia zmianę sposobu myślenia, którą miał. Nie ma w tym nic subiektywnego ani argumentującego. Zagłosuj, aby pozostać otwartym - to jedno z lepszych pytań oznaczonych jako „reszta”, które widziałem w SO.
Keith Gaughan
4
Keith, „wyjaśnianie zmiany nastawienia” to coś, co powinien zrobić na swoim blogu, a nie na SO.
John Saunders
13
Nie wyjaśnia swojej zmiany sposobu myślenia, pyta, czy jego zrozumienie jest dokładne.
aehlke
4
Doskonałe podsumowanie. Dowiedziałem się więcej z tego pytania niż z większości odpowiedzi.
Martin Konecny

Odpowiedzi:

21

Myślę, że twoje wyjaśnienie w większości to obejmuje. Identyfikatory URI to nieprzezroczyste identyfikatory, które w większości nie powinny być przekazywane poza identyfikator URI zakładki używany przez klienta użytkownika w celu uzyskania dostępu do aplikacji.

Jeśli chodzi o dokumentację, to pytanie zostało omówione kilka razy. Dokumentujesz swój typ multimediów wraz z zawartymi w nim kontrolkami hiperłącza (linkami i formularzami) oraz modelem interakcji, jeśli chcesz (zobacz AtomPub).

Jeśli dokumentujesz identyfikatory URI lub jak je zbudować, robisz to źle.

SerialSeb
źródło
Czy to nadal prawda? Istnieją specyfikacje odpowiedzi API, takie jak Ionspec, które celowo uczyniły te identyfikatory URI jako część odpowiedzi.
Sean Pianka
Tak, oni mają. W tym momencie należy ustalić, czy te udokumentowane identyfikatory URI są tylko punktami wejścia do aplikacji, które z pewnością pozostaną (kilka z nich nie jest rzadkich i całkiem przydatnych), czy też, ponieważ ludzie chcą generowania kodu, są one osadzane z specyfikację bezpośrednio do kodu, uniemożliwiając serwerowi poinformowanie klienta o tym, jak może działać. Jeśli klient myśli, że wie dzięki tej umowie, nie jesteś w hipermediach, jesteś w nowoczesnym modelu mydła openapi, z tymi samymi problemami, które napotkałeś 18 lat temu.
SerialSeb
Prawdą jest, że wiele języków dokumentacji API rozwinęło się w ciągu ostatnich 11 lat, ale podstawy nie uległy zmianie. Uważam, że wartość odkrywania tych linków lub przynajmniej wykrywania szablonów URI polega na tworzeniu ogólnego kodu klienta wielokrotnego użytku, który może je dynamicznie wykorzystywać, umożliwiając wielu implementacjom po stronie serwera ponowne wykorzystanie tego samego kodu klienta. Osadzanie URI nadal utrudnia takie scenariusze, ale jeśli używasz tych formatów, masz tendencję do ścisłego łączenia wygenerowanego klienta z tych specyfikacji, więc już straciłeś tę funkcję.
SerialSeb
8

Twoja interpretacja wydaje mi się poprawna. Wierzę, że ograniczenia Fieldinga można praktycznie zastosować.

Naprawdę chciałbym, aby ktoś opublikował kilka dobrych przykładów dokumentowania interfejsu REST. Jest tak wiele kiepskich przykładów, że kilka ważnych, na które można wskazać użytkownikom, byłoby bardzo cenne.

Darrel Miller
źródło
2
Łał. Ta strona z modelem zasobów wywołała łzę w moim oku. Miejmy nadzieję, że to zapoczątkuje trend.
Darrel Miller,
Szkoda, że ​​to w zasadzie jedyny przykład takiego API w sieci! Co gorsza, nie ma w ogóle dobrych przykładów kodu klienta zgodnego z zasadą (którą znalazłem).
jkp
1
@DarrelMiller Ale czy te typy mediów nie są zbyt „specyficzne”? Wydaje mi się, że ich API naprawdę używa tylko jednego MIME: application/jsoni że model zasobów to naprawdę relacje. Czy źle zrozumiałem ten aspekt REST? Przeczytałem również jedną z twoich odpowiedzi SO, która wydaje się wskazywać, że tych kontraktów „jednego atrybutu” należy unikać ...
edsioufi
2
@RichApodaca Twój link umarł na czerwonkę. web.archive.org/web/20170409132237/https://kenai.com/projects/…
forresthopkinsa
5

Szukałem dobrego przykładu interfejsu API napisanego zgodnie z HATEOAS i miałem problem ze znalezieniem takiego (stwierdziłem, że zarówno API SunCloud, jak i AtomPub są trudne do zastosowania w „normalnej” sytuacji API). Spróbowałem więc zrobić realistyczny przykład na moim blogu, postępując zgodnie z radami Roya Fieldingsa, co to znaczy być właściwą implementacją REST. Znalezienie tego przykładu było dla mnie bardzo trudne, mimo że jest on w zasadzie dość prosty (po prostu mylący podczas pracy z interfejsem API w przeciwieństwie do strony internetowej). Rozumiem, z czym Roy się nie zgadzał, i zgadzam się, że to tylko zmiana sposobu myślenia, aby poprawnie zaimplementować interfejs API.

Spójrz: Przykład API przy użyciu Rest

jeremyh
źródło
4

Jedynym wyjątkiem od udzielania instrukcji, jak budować URI, jest to, że dopuszczalne jest przesłanie szablonu URI w odpowiedzi hipertekstowej, z polami, które mają być automatycznie podstawione przez klienta, przy użyciu innych pól w hipertekście. Zwykle nie oszczędza to jednak dużej przepustowości, ponieważ kompresja gzip radzi sobie z powtarzającymi się częściami identyfikatorów URI na tyle dobrze, aby nie zawracać sobie tym głowy.

Kilka dobrych dyskusji na temat REST i związanych z nim HATEOAS:

Zalety (również) używania HATEOAS w interfejsach API RESTFul

JAK OTRZYMAĆ KAWĘ

aehlke
źródło
4

Dla zainteresowanych znalazłem szczegółowy przykład HATEOAS w praktyce w Sun Cloud API .

Rich Apodaca
źródło
2
Link nie żyje. Archiwum
niezależnie od tego, co
4

Większość ludzi popełnia błąd polega na tym, że (przynajmniej tak mi się wydaje) w świecie REST nie dokumentuje się swojego „interfejsu odpoczynku”, co dokumentuje się jako typ nośnika, niezależnie od serwera lub usługi.

redben
źródło
2

Myślę, że przez tyle lat, kiedy REST istnieje, technolodzy pogodzili się z koncepcją zasobu i tym, co naprawdę jest, a co nie jest RESTful.

Zgodnie z modelem dojrzałości Richardsona istnieją 4 poziomy (0-3), które definiują, jak REST -owy jest Twój interfejs API, przy czym 3 oznaczają prawdziwie RESTful API, tak jak chciał tego Roy Fielding.

Poziom 0 jest wtedy, gdy masz jeden identyfikator URI punktu wejścia - taki jak SOAP.

Poziom 1 oznacza, że ​​API jest w stanie rozróżnić różne zasoby i ma więcej niż jeden punkt wejścia - nadal pachnie SOAP.

Poziom 2 dotyczy czasowników HTTP - głównie GET, POST, DELETE. To jest poziom, na którym naprawdę pojawia się REST.

Na poziomie 3 zaczynasz używać elementów sterujących hipermedii, aby uczynić swoje API prawdziwie REST

Sugerowane linki do dalszego czytania:

Sampada
źródło
1

Absolutnie poprawne. Zwróciłbym ponadto uwagę, że szablony URI doskonale sprawdzają się w aplikacji zgodnej z REST, o ile wzorce pochodzą z dokumentów otrzymanych z serwera (odpowiednim przykładem jest OpenSearch). W przypadku szablonów URI dokumentujesz, gdzie są używane i jakie są oczekiwane symbole zastępcze w szablonie, ale nie same szablony. Nieco w przeciwieństwie do tego, co powiedział Wahnfrieden, nie jest to wyjątek.

Na przykład w mojej pracy mamy wewnętrzny system zarządzania domenami, a dokument serwisowy określa dwa szablony URI: jeden do tworzenia najlepszego zgadywanego URI dla zasobu domeny, a drugi do tworzenia identyfikatora URI do sprawdzania dostępności domeny. Nadal można przejrzeć kolekcję domen, aby dowiedzieć się, jaki jest identyfikator URI danej domeny, ale biorąc pod uwagę ogromną liczbę domen, którymi zarządza, nie byłoby to wykonalne dla klienta, więc dałoby mu możliwość odgadnięcia, co Identyfikator URI zasobu domeny może być olbrzymią korzyścią pod względem łatwości implementacji z punktu widzenia klienta i przepustowości z punktu widzenia serwera.

Wracając do pytania: nasza dokumentacja normatywna przedstawia zasoby, wpływ różnych metod na te zasoby oraz używane typy nośników reprezentacji i ich schematy, a także rodzaje zasobów, na które wskazują identyfikatory URI w tych reprezentacjach.

Dołączamy również dokumentację nienormatywną (informacyjną), do której dołączono zastrzeżenie, aby nie wczytywać zbyt wiele w identyfikatory URI wspomniane w dokumencie, co zawiera przykłady typowych interakcji klient-serwer. W ten sposób dość abstrakcyjna dokumentacja normatywna jest konkretna.

Keith Gaughan
źródło
1
Dobrze jest udostępniać szablony URI jako część interfejsu API poza pasmem. Po prostu PROSZĘ NIE odnosić się do tego jako ODPOCZYNKU, ponieważ tak nie jest. To ogromna ilość sprzężeń i dokładnie to, czego REST miał uniknąć. Ale jak mówisz, REST nie jest dla każdej aplikacji. Więc nie udawaj, że każda aplikacja jest REST.
aehlke
1
Właściwie się zgadzam. Myślę, że to właśnie powiedziałem. Jednak naprawdę nie widzę żadnego powodu, by udostępniać szablony URI poza pasmem.
Keith Gaughan,
0

Załóżmy, że GET /foos/createFormjest wywoływany, aby uzyskać wartości pól formularza, dla których należy podać, kiedy przechodzimy do tworzenia POST /foos. Teraz ten konkretny adres URL, tj. 1 używany do tworzenia foos, powinien być wymieniony w odpowiedzi GET /foos/createFormjako link do akcji przesyłania zgodnie z propozycją Fieldinga, prawda?
W takim razie jaka jest korzyść z mapowania akcji na dobrze znane czasowniki HTTP na akcje, rzecz „konwencja przez kod / konfigurację” zostaje anulowana.

redzedi
źródło