Szukam sposobu na zawinięcie interfejsów API wokół domyślnych funkcji w aplikacjach internetowych, bazach danych i CMS opartych na PHP.
Rozejrzałem się i znalazłem kilka szkieletów. Oprócz odpowiedzi na moje pytanie, istnieje Tonic , platforma REST, którą lubię, ponieważ jest bardzo lekka.
Najbardziej podoba mi się REST ze względu na jego prostotę i chciałbym na jego podstawie stworzyć architekturę API. Staram się omijać podstawowe zasady i jeszcze go nie rozumiem. Dlatego też szereg pytań.
1. Czy rozumiem, prawda?
Powiedzmy, że mam zasób „użytkowników”. Mógłbym skonfigurować wiele takich identyfikatorów URI:
/api/users when called with GET, lists users
/api/users when called with POST, creates user record
/api/users/1 when called with GET, shows user record
when called with PUT, updates user record
when called with DELETE, deletes user record
czy jest to jak dotąd poprawne przedstawienie architektury RESTful?
2. Potrzebuję więcej czasowników
Teoria tworzenia, aktualizacji i usuwania może wystarczyć, ale w praktyce będę potrzebować znacznie więcej czasowników. Zdaję sobie sprawę, że są to rzeczy, które mogą być osadzone w żądaniu aktualizacji, ale są to konkretne akcje, które mogą mieć określone kody powrotu i nie chciałbym, aby wszystkie były wrzucane w jedną akcję.
Niektóre, które przychodzą na myśl w przykładzie użytkownika to:
activate_login
deactivate_login
change_password
add_credit
jak wyraziłbym działania takie jak te w architekturze RESTful URL?
Moim instynktem byłoby wykonanie wywołania GET do adresu URL takiego jak
/api/users/1/activate_login
i oczekuj z powrotem kodu statusu.
To jednak odbiega od idei używania czasowników HTTP. Co myślisz?
3. Jak zwracać komunikaty o błędach i kody
Duża część piękna REST wynika z zastosowania standardowych metod HTTP. W przypadku błędu wysyłam nagłówek z kodem błędu 3xx, 4xx lub 5xx. Aby uzyskać szczegółowy opis błędu, mogę użyć treści (prawda?). Na razie w porządku. Ale jaki byłby sposób przesłania zastrzeżonego kodu błędu, który jest bardziej szczegółowy w opisie tego, co poszło źle (np. „Nie udało się połączyć z bazą danych” lub „błędne logowanie do bazy danych”)? Jeśli umieszczę go w ciele wraz z wiadomością, muszę go później przeanalizować. Czy istnieje standardowy nagłówek do tego rodzaju rzeczy?
4. Jak przeprowadzić uwierzytelnianie
- Jak wyglądałoby uwierzytelnianie oparte na kluczu API zgodnie z zasadami REST?
- Czy istnieją mocne strony, by nie używać sesji podczas uwierzytelniania klienta REST, poza tym, że jest to rażące naruszenie zasady REST? :) (tylko połowa żartów tutaj, uwierzytelnianie oparte na sesji dobrze bawi się z moją istniejącą infrastrukturą).
źródło
Odpowiedzi:
Zauważyłem to pytanie kilka dni później, ale czuję, że mogę dodać trochę wglądu. Mam nadzieję, że może to być pomocne w przedsięwzięciu RESTful.
Punkt 1: Czy rozumiem, prawda?
Dobrze zrozumiałeś. To poprawna reprezentacja architektury RESTful. Poniższa matryca z Wikipedii może być bardzo pomocna w definiowaniu rzeczowników i czasowników:
W przypadku identyfikatora URI kolekcji, takiego jak:
http://example.com/resources/
POBIERZ : Lista członków kolekcji wraz z ich identyfikatorami URI członków w celu dalszej nawigacji. Na przykład wymień wszystkie samochody na sprzedaż.
PUT : Znaczenie zdefiniowane jako „zastąp całą kolekcję inną kolekcją”.
POST : Utwórz nowy wpis w kolekcji, w którym identyfikator jest automatycznie przypisywany przez kolekcję. Utworzony identyfikator jest zwykle dołączany jako część danych zwracanych przez tę operację.
USUŃ : Znaczenie zdefiniowane jako „usuń całą kolekcję”.
W przypadku identyfikatora URI członka, takiego jak:
http://example.com/resources/7HOU57Y
POBIERZ : pobierz reprezentację adresowanego członka kolekcji wyrażoną odpowiednim typem MIME.
PUT : Zaktualizuj adresowanego członka kolekcji lub utwórz go z określonym identyfikatorem.
POST : Traktuje adresowanego członka jako zbiór sam w sobie i tworzy nowego podwładnego.
USUŃ : Usuń adresowanego członka kolekcji.
Punkt 2: Potrzebuję więcej czasowników
Ogólnie rzecz biorąc, jeśli uważasz, że potrzebujesz więcej czasowników, może to w rzeczywistości oznaczać konieczność ponownego zidentyfikowania zasobów. Pamiętaj, że w REST zawsze działasz na zasobie lub na zbiorze zasobów. To, co wybierzesz jako zasób, jest dość ważne dla definicji interfejsu API.
Aktywuj / dezaktywuj logowanie : jeśli tworzysz nową sesję, możesz rozważyć „sesję” jako zasób. Aby utworzyć nową sesję, użyj POST do
http://example.com/sessions/
poświadczeń w treści. Aby wygasnąć, użyj PUT lub DELETE (być może w zależności od tego, czy zamierzasz zachować historię sesji)http://example.com/sessions/SESSION_ID
.Zmień hasło: Tym razem zasobem jest „użytkownik”. Potrzebujesz PUT
http://example.com/users/USER_ID
ze starymi i nowymi hasłami w ciele. Działasz na zasobie „użytkownika”, a hasło zmiany jest po prostu żądaniem aktualizacji. Jest dość podobny do instrukcji UPDATE w relacyjnej bazie danych.Jest to sprzeczne z bardzo podstawową zasadą REST: Prawidłowe użycie czasowników HTTP. Każde żądanie GET nigdy nie powinno pozostawiać żadnych skutków ubocznych.
Na przykład żądanie GET nigdy nie powinno tworzyć sesji w bazie danych, zwracać pliku cookie z nowym identyfikatorem sesji ani pozostawiać żadnych pozostałości na serwerze. Czasownik GET jest jak instrukcja SELECT w silniku bazy danych. Pamiętaj, że odpowiedź na każde żądanie z czasownikiem GET powinna mieć możliwość buforowania, gdy zostaniesz o to poproszony z tymi samymi parametrami, tak jak na żądanie statycznej strony internetowej.
Punkt 3: Jak zwracać komunikaty o błędach i kody
Rozważ kody statusu HTTP 4xx lub 5xx jako kategorie błędów. Możesz opracować błąd w ciele.
Nie udało się połączyć z bazą danych: / Niepoprawne logowanie do bazy danych : Zasadniczo powinieneś użyć błędu 500 dla tego typu błędów. Jest to błąd po stronie serwera. Klient nie zrobił nic złego. 500 błędów zwykle uważa się za „możliwe do powtórzenia”. tzn. klient może ponowić to samo dokładne żądanie i oczekiwać, że zostanie zrealizowane po rozwiązaniu problemów z serwerem. Podaj szczegóły w ciele, aby klient mógł przedstawić nam kontekst ludzi.
Inną kategorią błędów byłaby rodzina 4xx, co ogólnie wskazuje, że klient zrobił coś złego. W szczególności ta kategoria błędów zwykle wskazuje klientowi, że nie ma potrzeby ponawiania żądania w jego obecnym kształcie, ponieważ będzie ono nadal ulegać ciągłemu niepowodzeniu. tzn. klient musi coś zmienić przed ponowieniem tego żądania. Na przykład błędy „Nie znaleziono zasobu” (HTTP 404) lub „Błędne żądanie” (HTTP 400) należą do tej kategorii.
Punkt 4: Jak przeprowadzić uwierzytelnianie
Jak wskazano w punkcie 1, zamiast uwierzytelniać użytkownika, możesz pomyśleć o utworzeniu sesji. Otrzymasz nowy „Identyfikator sesji” wraz z odpowiednim kodem stanu HTTP (200: przyznany dostęp lub 403: odmowa dostępu).
Następnie zapytasz serwer RESTful: „Czy możesz uzyskać zasoby dla tego identyfikatora sesji?”.
Nie ma trybu uwierzytelnionego - REST jest bezstanowy: tworzysz sesję, prosisz serwer o udostępnienie zasobów za pomocą tego identyfikatora sesji jako parametru, a po wylogowaniu przerywasz lub wygasa sesja.
źródło
PUT
hasła do zmiany hasła jest prawdopodobnie nieprawidłowe;PUT
wymaga całego zasobu, więc musisz wysłać wszystkie atrybuty użytkownika, aby zachować zgodność z HTTP (a zatem i REST HATEOAS). Zamiast tego po prostu zmień hasło należy użyćPATCH
lubPOST
.Mówiąc najprościej, robisz to całkowicie wstecz.
Nie powinieneś podchodzić do tego z jakich adresów URL powinieneś używać. Adresy URL pojawią się „za darmo”, gdy zdecydujesz, jakie zasoby są niezbędne dla twojego systemu ORAZ w jaki sposób będziesz reprezentować te zasoby oraz interakcje między zasobami a stanem aplikacji.
Cytując Roy Fielding
Ludzie zawsze zaczynają od identyfikatorów URI i myślą, że to jest rozwiązanie, a potem brakuje im kluczowej koncepcji w architekturze REST, w szczególności, jak cytowano powyżej: „Brak tutaj oznacza, że informacje pozapasmowe napędzają interakcję zamiast hipertekstu. „
Szczerze mówiąc, wiele osób widzi wiele identyfikatorów URI i niektórych GET, PUT i POST i uważa, że REST jest łatwy. REST nie jest łatwe. RPC przez HTTP jest łatwe, przenoszenie obiektów BLOB danych tam iz powrotem za pośrednictwem ładunków HTTP jest łatwe. Jednak REST wykracza poza to. REST jest niezależny od protokołu. HTTP jest po prostu bardzo popularny i odpowiedni dla systemów REST.
REST występuje w typach mediów, ich definicjach i sposobie, w jaki aplikacja steruje działaniami dostępnymi dla tych zasobów za pośrednictwem hipertekstu (efektywnie łączy).
Istnieją różne poglądy na temat typów mediów w systemach REST. Niektóre preferują ładunki specyficzne dla aplikacji, podczas gdy inne, takie jak podnoszenie istniejących typów mediów do ról odpowiednich dla aplikacji. Na przykład, z jednej strony, masz określone schematy XML dostosowane do twojej aplikacji, w przeciwieństwie do używania czegoś takiego jak XHTML jako reprezentacji, być może za pomocą mikroformatów i innych mechanizmów.
Wydaje mi się, że oba podejścia mają swoje miejsce, XHTML działa bardzo dobrze w scenariuszach, które pokrywają się zarówno z siecią napędzaną przez człowieka, jak i przez maszynę, podczas gdy poprzednie, bardziej specyficzne typy danych lepiej czuję ułatwiają interakcje między maszynami. Uważam, że podnoszenie formatów towarowych może potencjalnie utrudniać negocjowanie treści. „application / xml + yourresource” jest o wiele bardziej specyficzny jako typ nośnika niż „application / xhtml + xml”, ponieważ ten ostatni może dotyczyć wielu ładunków, które mogą być lub nie być czymś, czym tak naprawdę interesuje się klient maszyny, ani nie może ustal bez introspekcji.
Jednak XHTML działa bardzo dobrze (oczywiście) w ludzkiej sieci, w której przeglądarki i rendering są bardzo ważne.
Twoja aplikacja poprowadzi Cię w tego rodzaju decyzjach.
Częścią procesu projektowania systemu REST jest odkrywanie w systemie pierwszorzędnych zasobów wraz z pochodnymi zasobami pomocniczymi niezbędnymi do obsługi operacji na zasobach podstawowych. Po odkryciu zasobów, reprezentacja tych zasobów, a także diagramy stanów przedstawiające przepływ zasobów poprzez hipertekst w reprezentacjach, ponieważ jest to kolejne wyzwanie.
Przypomnij sobie, że każda reprezentacja zasobu w systemie hipertekstowym łączy zarówno rzeczywistą reprezentację zasobu, jak i przejścia stanu dostępne dla zasobu. Rozważ każdy zasób jako węzeł na wykresie, a łącza to linie wychodzące z tego węzła do innych stanów. Te linki informują klientów nie tylko o tym, co można zrobić, ale także o tym, co jest im potrzebne (ponieważ dobre łącze łączy w sobie identyfikator URI i wymagany typ nośnika).
Na przykład możesz mieć:
Twoja dokumentacja będzie mówić o polu rel o nazwie „users” oraz typie mediów „application / xml + youruser”.
Te linki mogą wydawać się zbędne, wszystkie rozmawiają z tym samym URI. Ale nie są.
Wynika to z faktu, że w relacji „użytkownicy” ten link mówi o kolekcji użytkowników, a do pracy z kolekcją można użyć jednolitego interfejsu (GET, aby odzyskać wszystkie, DELETE, aby usunąć wszystkie itp.)
Jeśli prześlesz ten adres URL, będziesz musiał przekazać dokument „application / xml + usercollection”, który prawdopodobnie będzie zawierał tylko jedną instancję użytkownika w dokumencie, abyś mógł dodać użytkownika, a może nie dodać kilku na pewnego razu. Być może twoja dokumentacja sugeruje, że możesz po prostu przekazać jeden typ użytkownika zamiast kolekcji.
Możesz zobaczyć, czego wymaga aplikacja do przeprowadzenia wyszukiwania, zgodnie z definicją linku „szukaj” i jego typu mediacji. Dokumentacja typu nośnika wyszukiwania pokaże Ci, jak się to zachowuje i czego można oczekiwać jako wyników.
Na wynos tutaj jednak same URI są w zasadzie nieistotne. Aplikacja kontroluje identyfikatory URI, a nie klientów. Poza kilkoma „punktami wejścia”, klienci powinni polegać na identyfikatorach URI dostarczonych przez aplikację do jej pracy.
Klient musi wiedzieć, jak manipulować i interpretować typy mediów, ale nie musi bardzo dbać o to, dokąd idzie.
Te dwa łącza są semantycznie identyczne w oczach klientów:
Skoncentruj się na swoich zasobach. Skoncentruj się na zmianach stanu w aplikacji i na tym, jak najlepiej to osiągnąć.
źródło
do 1 : Jak dotąd wygląda dobrze. Pamiętaj, aby zwrócić identyfikator URI nowo utworzonego użytkownika w nagłówku „Lokalizacja:” jako część odpowiedzi na POST wraz z kodem statusu „201 Utworzono”.
do 2: Aktywacja przez GET jest złym pomysłem, a umieszczenie czasownika w URI to zapach projektowy. Możesz rozważyć zwrot formularza na GET. W aplikacji internetowej byłby to formularz HTML z przyciskiem przesyłania; w przypadku użycia interfejsu API możesz chcieć zwrócić reprezentację zawierającą identyfikator URI do PUT w celu aktywacji konta. Oczywiście możesz dołączyć ten identyfikator URI również w odpowiedzi na POST do / users. Użycie PUT sprawi, że twoje żądanie będzie idempotentne, tzn. Może zostać bezpiecznie wysłane ponownie, jeśli klient nie jest pewien sukcesu. Ogólnie rzecz biorąc, zastanów się, w jakie zasoby możesz zmienić swoje czasowniki (rodzaj „nounification czasowników”). Zadaj sobie pytanie, z jaką metodą Twoje konkretne działanie jest najbardziej dostosowane. Np. Hasło_zmian -> PUT; dezaktywuj -> prawdopodobnie USUŃ; add_credit -> ewentualnie POST lub PUT.
do 3. Nie wymyślaj nowych kodów statusu, chyba że uważasz, że są one tak ogólne, że zasługują na standaryzację globalną. Staraj się używać najbardziej odpowiedniego dostępnego kodu stanu (przeczytaj o wszystkich z nich w RFC 2616). Dołącz dodatkowe informacje do treści odpowiedzi. Jeśli naprawdę, naprawdę jesteś pewien, że chcesz wymyślić nowy kod stanu, pomyśl jeszcze raz; jeśli nadal tak uważasz, upewnij się, że wybrałeś przynajmniej odpowiednią kategorię (1xx -> OK, 2xx -> informacyjne, 3xx -> przekierowanie; 4xx-> błąd klienta, 5xx -> błąd serwera). Czy wspominałem, że wymyślanie nowych kodów stanu to zły pomysł?
do 4. Jeśli w jakikolwiek sposób jest to możliwe, użyj struktury uwierzytelniania wbudowanej w HTTP. Sprawdź, jak Google dokonuje uwierzytelnienia w GData. Zasadniczo nie należy umieszczać kluczy API w identyfikatorach URI. Staraj się unikać sesji w celu zwiększenia skalowalności i obsługi buforowania - jeśli odpowiedź na żądanie różni się z powodu czegoś, co zdarzyło się wcześniej, zwykle przywiązujesz się do konkretnej instancji procesu serwera. O wiele lepiej jest przekształcić stan sesji w dowolny stan klienta (np. Uczynić go częścią kolejnych żądań) lub jawnie, przekształcając go w stan zasobu (serwera), tj. Nadając mu własny identyfikator URI.
źródło
1. Masz dobry pomysł, jak zaprojektować swoje zasoby, IMHO. Nic bym nie zmienił.
2. Zamiast próbować rozszerzyć HTTP o więcej czasowników, zastanów się, do czego możesz zredukować proponowane czasowniki pod względem podstawowych metod i zasobów HTTP. Na przykład zamiast
activate_login
czasownika można skonfigurować zasoby typu:/api/users/1/login/active
który jest prostym boolowskim. Aby aktywować login, wystarczyPUT
dokument „prawda”, 1 lub cokolwiek innego. Aby dezaktywować,PUT
dokument, który jest pusty lub zawiera 0 lub fałsz.Podobnie, aby zmienić lub ustawić hasło, po prostu wykonaj
PUT
s/api/users/1/password
.Ilekroć musisz dodać coś (np. Kredyt), pomyśl w kategoriach
POST
s. Na przykład, możesz zrobić aPOST
dla zasobu takiego jak/api/users/1/credits
ciało zawierające liczbę kredytów do dodania. APUT
w tym samym zasobie można użyć do zastąpienia wartości zamiast dodawania. APOST
z liczbą ujemną w ciele odejmowałoby się i tak dalej.3. Zdecydowanie odradzam rozszerzanie podstawowych kodów stanu HTTP. Jeśli nie możesz znaleźć takiego, który dokładnie pasuje do Twojej sytuacji, wybierz najbliższy i podaj szczegóły błędu w treści odpowiedzi. Pamiętaj też, że nagłówki HTTP są rozszerzalne; Twoja aplikacja może zdefiniować wszystkie niestandardowe nagłówki, które lubisz. Na przykład jedna aplikacja, nad którą pracowałem, może zwrócić
404 Not Found
w wielu okolicznościach. Z tego powodu zamiast zmuszać klienta do przeanalizowania treści odpowiedzi, właśnie dodaliśmy nowy nagłówekX-Status-Extended
, który zawierał nasze zastrzeżone rozszerzenia kodów stanu. Możesz więc zobaczyć odpowiedź:W ten sposób klient HTTP, taki jak przeglądarka internetowa, nadal będzie wiedział, co zrobić ze zwykłym kodem 404, a bardziej zaawansowany klient HTTP może wybrać
X-Status-Extended
bardziej szczegółowe informacje w nagłówku.4. W celu uwierzytelnienia zalecam używanie uwierzytelniania HTTP, jeśli możesz. Ale IMHO nie ma nic złego w korzystaniu z uwierzytelniania opartego na plikach cookie, jeśli jest to dla Ciebie łatwiejsze.
źródło
Podstawy REST
REST ma jednolite ograniczenie interfejsu, co oznacza, że klient REST musi polegać na standardach zamiast szczegółowych informacji dotyczących konkretnej usługi REST specyficznych dla aplikacji, więc klient REST nie przełamie drobnych zmian i prawdopodobnie będzie można go ponownie użyć.
Więc istnieje umowa między klientem REST a usługą REST. Jeśli użyjesz protokołu HTTP jako protokołu bazowego, następujące standardy są częścią umowy:
REST ma ograniczenie bezstanowe, które deklaruje, że komunikacja między usługą REST a klientem musi być bezstanowa. Oznacza to, że usługa REST nie może utrzymywać stanów klienta, więc nie można przechowywać pamięci po stronie serwera. Musisz uwierzytelnić każde pojedyncze żądanie. Na przykład podstawowe uwierzytelnianie HTTP (część standardu HTTP) jest w porządku, ponieważ wysyła nazwę użytkownika i hasło przy każdym żądaniu.
Aby odpowiedzieć na pytania
Tak, to może być.
Wystarczy wspomnieć, że klienci nie dbają o strukturę IRI, dbają o semantykę, ponieważ podążają za linkami posiadającymi atrybuty relacji łącza lub danych połączonych (RDF).
Jedyną ważną rzeczą w IRI jest to, że pojedynczy IRI musi identyfikować tylko jeden zasób. Pojedynczy zasób, taki jak użytkownik, może mieć wiele różnych IRI.
To całkiem proste, dlaczego używamy ładnych IRI, takich jak
/users/123/password
; znacznie łatwiej jest napisać logikę routingu na serwerze, gdy zrozumiesz IRI, po prostu czytając go.Masz więcej czasowników, takich jak PUT, PATCH, OPCJE, a nawet więcej, ale nie potrzebujesz ich więcej ... Zamiast dodawać nowe czasowniki, musisz nauczyć się, jak dodawać nowe zasoby.
activate_login -> PUT /login/active true deactivate_login -> PUT /login/active false change_password -> PUT /user/xy/password "newpass" add_credit -> POST /credit/raise {details: {}}
(Logowanie nie ma sensu z punktu widzenia REST, z powodu ograniczenia bezstanowego).
Twoi użytkownicy nie dbają o przyczynę problemu. Chcą wiedzieć tylko, czy wystąpił sukces lub błąd, i prawdopodobnie komunikat o błędzie, który mogą zrozumieć, na przykład: „Przykro nam, ale nie byliśmy w stanie zapisać Twojego posta.” Itp.
Nagłówki statusu HTTP to standardowe nagłówki. Wszystko inne powinno znajdować się w ciele. Pojedynczy nagłówek nie wystarczy, aby opisać na przykład szczegółowe wielojęzyczne komunikaty o błędach.
Ograniczenie bezstanowe (wraz z pamięcią podręczną i warstwowymi ograniczeniami systemowymi) zapewnia prawidłowe skalowanie usługi. Na pewno nie chcesz utrzymywać milionów sesji na serwerze, kiedy możesz zrobić to samo na klientach ...
Klient zewnętrzny otrzymuje token dostępu, jeśli użytkownik przyzna mu dostęp za pomocą głównego klienta. Następnie klient zewnętrzny wysyła token dostępu do każdego żądania. Istnieją bardziej skomplikowane rozwiązania, na przykład możesz podpisywać każde pojedyncze żądanie itp. W celu uzyskania dalszych informacji sprawdź instrukcję OAuth.
Literatura pokrewna
Rozprawa doktorska Roy Thomas Fielding (autor REST)
2000, University of California, Irvine
Markusa Lanthalera (współautor JSON-LD i autor Hydry)
2014, Politechnika w Grazu, Austria
źródło
W podanych przez ciebie przykładach użyłbym:
Activ_login
POST /users/1/activation
dezaktywuj_logowanie
DELETE /users/1/activation
Zmień hasło
PUT /passwords
(zakłada to, że użytkownik jest uwierzytelniony)Dodaj kredyt
POST /credits
(zakłada to, że użytkownik jest uwierzytelniony)W przypadku błędów zwrócisz błąd w treści w formacie, w którym otrzymałeś żądanie, więc jeśli otrzymasz:
DELETE /users/1.xml
Odesłałbyś odpowiedź z powrotem w formacie XML, to samo dotyczy JSON itp.
Do uwierzytelnienia należy użyć uwierzytelniania HTTP.
źródło
create
jako części identyfikatora URI (pamiętaj, że identyfikatory URI powinny być rzeczownikami, a metody HTTP powinny być czasownikami działającymi na tych rzeczownikach). Zamiast tego miałbym zasób,/users/1/active
który może być prostym boolowskim i może być ustawiane przez umieszczenie 1 lub 0 dla tego zasobu.activation
tego identyfikatora URI, chyba że jawnie będziesz manipulował zasobem i zarządzał nim pod nazwą/users/1/activation
. Co robi GET? Co robi PUT? Na pewno czuję, że weryfikujesz URI. Ponadto, tak jak w przypadku negocjacji typu zawartości, często najlepiej jest pominąć ten identyfikator URI i wstawić go do nagłówkówAccept
.źródło
Sugerowałbym (jako pierwsze przejście), który
PUT
powinien być używany tylko do aktualizacji istniejących jednostek.POST
powinny być używane do tworzenia nowych. to znaczynie wydaje mi się właściwe. Reszta pierwszej sekcji (użycie czasownika) wygląda jednak logicznie.
źródło
Pełne, ale skopiowane ze specyfikacji metody HTTP 1.1 pod adresem http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
9.3 GET
Metoda GET oznacza pobieranie wszelkich informacji (w formie encji) identyfikowanych przez identyfikator URI żądania. Jeśli identyfikator URI żądania odnosi się do procesu generowania danych, to dane wytworzone zostaną zwrócone jako byt w odpowiedzi, a nie tekst źródłowy procesu, chyba że tekst ten jest wynikiem procesu.
Semantyka metody GET zmienia się na „warunkowy GET”, jeśli komunikat żądania zawiera pole nagłówka If-Modified-Since, If-Unmodified-Since, If-Match, If-None-Match lub If-Range. Warunkowa metoda GET wymaga, aby jednostka została przesłana tylko w okolicznościach opisanych w polach warunkowych nagłówków. Warunkowa metoda GET ma na celu ograniczenie niepotrzebnego użycia sieci, umożliwiając odświeżanie buforowanych jednostek bez konieczności wielokrotnego żądania lub przesyłania danych przechowywanych już przez klienta.
Semantyka metody GET zmienia się na „częściowy GET”, jeśli komunikat żądania zawiera pole nagłówka Range. Częściowe żądanie GET wymaga przeniesienia tylko części jednostki, jak opisano w sekcji 14.35. Metoda częściowego GET ma na celu zmniejszenie niepotrzebnego użycia sieci, umożliwiając ukończenie częściowo pobranych jednostek bez przesyłania danych przechowywanych już przez klienta.
Odpowiedź na żądanie GET jest buforowalna, tylko jeśli spełnia wymagania dotyczące buforowania HTTP opisane w sekcji 13.
Uwagi dotyczące bezpieczeństwa w przypadku formularzy znajdują się w sekcji 15.1.3.
9.5 POST
Metoda POST służy do żądania, aby serwer źródłowy zaakceptował jednostkę zawartą w żądaniu jako nowego podwładnego zasobu określonego przez identyfikator URI żądania w wierszu żądania. POST został zaprojektowany, aby umożliwić jednolitą metodę obejmującą następujące funkcje:
Rzeczywista funkcja wykonywana metodą POST jest określana przez serwer i zwykle zależy od URI żądania. Wysłana jednostka jest podporządkowana temu identyfikatorowi URI w taki sam sposób, w jaki plik jest podporządkowany katalogowi zawierającemu go, artykuł z wiadomościami jest podporządkowany grupie dyskusyjnej, do której jest wysyłany, lub rekord jest podporządkowany bazie danych.
Czynność wykonana metodą POST może nie skutkować zasobem, który można zidentyfikować za pomocą identyfikatora URI. W takim przypadku albo 200 (OK), albo 204 (Brak treści) jest odpowiednim statusem odpowiedzi, w zależności od tego, czy odpowiedź zawiera encję, która opisuje wynik.
Jeśli zasób został utworzony na serwerze źródłowym, odpowiedzią POWINNA być 201 (Utworzony) i zawierać byt opisujący stan żądania i odnoszący się do nowego zasobu oraz nagłówek Lokalizacji (patrz sekcja 14.30).
Odpowiedzi na tę metodę nie są buforowane, chyba że odpowiedź zawiera odpowiednie pola nagłówka Cache-Control lub Expires. Jednak odpowiedź 303 (Zobacz inne) może być użyta do nakierowania agenta użytkownika na pobranie zasobu buforowanego.
Żądania POST MUSZĄ być zgodne z wymogami dotyczącymi przesyłania komunikatów określonymi w sekcji 8.2.
Informacje na temat bezpieczeństwa znajdują się w sekcji 15.1.3.
9,6 PUT
Metoda PUT żąda, aby zamknięta jednostka była przechowywana pod dostarczonym URI żądania. Jeśli identyfikator URI żądania odnosi się do już istniejącego zasobu, dołączony byt MUSI być uważany za zmodyfikowaną wersję tego, który znajduje się na serwerze źródłowym. Jeśli identyfikator URI żądania nie wskazuje na istniejący zasób, a ten identyfikator URI może zostać zdefiniowany jako nowy zasób przez żądającego agenta użytkownika, serwer źródłowy może utworzyć zasób z tym identyfikatorem URI. Jeśli zostanie utworzony nowy zasób, serwer źródłowy MUSI poinformować klienta użytkownika za pomocą odpowiedzi 201 (Utworzono). Jeśli istniejący zasób zostanie zmodyfikowany, POWINNY zostać wysłane kody odpowiedzi 200 (OK) lub 204 (brak treści), aby wskazać pomyślne zakończenie żądania. Jeśli nie można utworzyć lub zmodyfikować zasobu za pomocą identyfikatora URI żądania, POWINNA zostać podana odpowiednia odpowiedź na błąd, która odzwierciedla charakter problemu. Odbiorca jednostki NIE MOŻE zignorować żadnych nagłówków Content- * (np. Content-Range), których nie rozumie ani nie wdraża, i MUSI zwrócić odpowiedź 501 (Nie zaimplementowano) w takich przypadkach.
Jeśli żądanie przechodzi przez pamięć podręczną, a identyfikator URI żądania identyfikuje jedną lub więcej aktualnie buforowanych jednostek, wpisy MUSZĄ być traktowane jako nieaktualne. Odpowiedzi na tę metodę nie są buforowane.
Podstawowa różnica między żądaniami POST i PUT znajduje odzwierciedlenie w innym znaczeniu URI żądania. Identyfikator URI w żądaniu POST identyfikuje zasób, który będzie obsługiwał zamknięty obiekt. Ten zasób może być procesem akceptującym dane, bramą do innego protokołu lub osobnym podmiotem, który przyjmuje adnotacje. W przeciwieństwie do tego, URI w żądaniu PUT identyfikuje encję zawartą w żądaniu - agent użytkownika wie, jaki jest URI, a serwer NIE MOŻE próbować zastosować żądania do jakiegoś innego zasobu. Jeśli serwer chce zastosować żądanie do innego identyfikatora URI,
MUSI wysłać odpowiedź 301 (Moved Permanently); klient użytkownika MOŻE następnie podjąć własną decyzję dotyczącą tego, czy przekierować żądanie.
Jeden zasób MOŻE być identyfikowany przez wiele różnych identyfikatorów URI. Na przykład artykuł może mieć identyfikator URI do identyfikowania „bieżącej wersji”, który jest niezależny od identyfikatora URI identyfikującego każdą konkretną wersję. W takim przypadku żądanie PUT dotyczące ogólnego identyfikatora URI może spowodować zdefiniowanie kilku innych identyfikatorów URI przez serwer pochodzenia.
HTTP / 1.1 nie określa, w jaki sposób metoda PUT wpływa na stan serwera źródłowego.
Żądania PUT MUSZĄ spełniać wymagania dotyczące przesyłania wiadomości określone w sekcji 8.2.
O ile nie określono inaczej dla konkretnego nagłówka encji, nagłówki encji w żądaniu PUT POWINNY być stosowane do zasobu utworzonego lub zmodyfikowanego przez PUT.
9.7 USUŃ
Metoda DELETE żąda, aby serwer pochodzenia usunął zasób zidentyfikowany przez URI żądania. Ta metoda MOŻE zostać zastąpiona przez interwencję człowieka (lub w inny sposób) na serwerze źródłowym. Nie można zagwarantować klientowi, że operacja została wykonana, nawet jeśli kod statusu zwrócony z serwera źródłowego wskazuje, że akcja została wykonana pomyślnie. Jednak serwer NIE POWINIEN wskazywać sukcesu, chyba że w chwili udzielenia odpowiedzi zamierza usunąć zasób lub przenieść go w niedostępną lokalizację.
Pomyślna odpowiedź POWINNA wynosić 200 (OK), jeśli odpowiedź zawiera jednostkę opisującą status, 202 (Zaakceptowana), jeśli akcja nie została jeszcze podjęta, lub 204 (Brak treści), jeśli akcja została podjęta, ale odpowiedź nie obejmuje jednostka.
Jeśli żądanie przechodzi przez pamięć podręczną, a identyfikator URI żądania identyfikuje jedną lub więcej aktualnie buforowanych jednostek, wpisy MUSZĄ być traktowane jako nieaktualne. Odpowiedzi na tę metodę nie są buforowane.
źródło
O kodach powrotu REST: błędne jest mieszanie kodów protokołu HTTP i wyników REST.
Widziałem jednak wiele implementacji mieszających je i wielu programistów może się ze mną nie zgodzić.
Kody zwrotne HTTP są powiązane z samym
HTTP Request
sobą. Wywołanie REST jest wykonywane przy użyciu żądania protokołu przesyłania hipertekstu i działa na niższym poziomie niż sama wywołana metoda REST. REST jest koncepcją / podejściem, a jego wynik jest wynikiem biznesowym / logicznym , podczas gdy kod wyniku HTTP jest kodem transportowym .Na przykład zwracanie „404 Nie znaleziono”, gdy dzwonisz / users /, jest mylące, ponieważ może to oznaczać:
„403 Zabroniony / Odmowa dostępu” może oznaczać:
Lista może być kontynuowana z błędem „500 Server error” (błąd rzucenia HTTP Apache / Nginx lub błąd ograniczeń biznesowych w REST) lub innymi błędami HTTP itp.
Na podstawie kodu trudno zrozumieć, co było przyczyną niepowodzenia, awarii HTTP (transportu) lub awarii REST (logicznej).
Jeśli żądanie HTTP zostało fizycznie wykonane pomyślnie, zawsze powinno zwrócić kod 200, niezależnie od tego, czy rekord (y) został znaleziony, czy nie. Ponieważ zasób URI został znaleziony i był obsługiwany przez serwer http. Tak, może zwrócić pusty zestaw. Czy można otrzymać pustą stronę internetową z wynikiem 200 jako http, prawda?
Zamiast tego możesz zwrócić 200 kod HTTP i po prostu JSON z pustą tablicą / obiektem lub użyć flagi wynik bool / sukces, aby poinformować o statusie wykonanej operacji.
Ponadto niektórzy dostawcy Internetu mogą przechwycić twoje żądania i zwrócić ci kod 404 http. Nie oznacza to, że twoich danych nie znaleziono, ale na poziomie transportu coś jest nie tak.
Z Wiki :
źródło