Zgodnie ze specyfikacją HTTP / 1.1:
POST
Metoda służy do wniosku, że serwer pochodzenie zaakceptować podmiot ujęty w żądaniu jako nowy podległych zasobu zidentyfikowanych przezRequest-URI
wRequest-Line
Innymi słowy, POST
służy do tworzenia .
Te
PUT
wnioski, że metoda zamknięta jednostka być przechowywane pod dostarczonyRequest-URI
. JeśliRequest-URI
odnosi się do już istniejącego zasobu, zamknięty obiekt MUSI być uważany za zmodyfikowaną wersję tego, który znajduje się na serwerze źródłowym. JeśliRequest-URI
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. ”
Oznacza to, że PUT
służy do tworzenia lub zastępowania .
Którego należy użyć do stworzenia zasobu? Czy trzeba wspierać oba?
Odpowiedzi:
Ogólnie:
Do tworzenia można użyć zarówno PUT, jak i POST.
Musisz zapytać „do czego wykonujesz akcję?” aby rozróżnić, czego powinieneś używać. Załóżmy, że projektujesz interfejs API do zadawania pytań. Jeśli chcesz użyć POST, zrobiłbyś to z listą pytań. Jeśli chcesz użyć PUT, zrobiłbyś to dla konkretnego pytania.
Można używać zarówno jednego, jak i drugiego w moim projekcie RESTful:
Nie musisz obsługiwać zarówno PUT, jak i POST.
To, co jest używane, należy do Ciebie. Pamiętaj jednak, aby użyć właściwego w zależności od tego, do którego obiektu odwołujesz się w żądaniu.
Kilka uwag:
Przykład:
Napisałem następujące jako część innej odpowiedzi na SO w tej sprawie :
Dodatkowo i nieco bardziej zwięźle, RFC 7231 Sekcja 4.3.4 Stany PUT (wyróżnienie dodane),
źródło
W Internecie można znaleźć twierdzenia, które mówią
Żadne z nich nie ma racji.
Lepiej jest wybierać między PUT a POST w oparciu o idempotencję akcji.
PUT oznacza umieszczenie zasobu - całkowite zastąpienie tego, co jest dostępne pod danym adresem URL, inną rzeczą. Z definicji PUT jest idempotentny. Zrób to tyle razy, ile chcesz, a wynik będzie taki sam.
x=5
jest idempotentny. Możesz PUT zasób, czy już istnieje, czy nie (np. W celu utworzenia lub aktualizacji)!POST aktualizuje zasób, dodaje zasób pomocniczy lub powoduje zmianę. POST nie jest idempotentny w sposób, który
x++
nie jest idempotentny.Według tego argumentu PUT służy do tworzenia, gdy znasz adres URL rzeczy, którą utworzysz. POST można wykorzystać do utworzenia, gdy znasz adres URL „fabryki” lub menedżera dla kategorii rzeczy, którą chcesz utworzyć.
więc:
lub:
źródło
name
idate
. Jeśli mamy jednostkę z istniejącąname
idate
, ale następnie dokonać żądania do niego określające jedyniename
, właściwe zachowanie PUT byłoby zatrzećdate
podmiotu, podczas POST może aktualizować określony tylko właściwości, pozostawiając właściwości nieokreślone, gdyż były one przed złożeniem wniosku. Czy to brzmi poprawnie / rozsądnie, czy też jest to niewłaściwe użycie PUT (widziałem odniesienia do PATCH , które wydają się bardziej odpowiednie, ale jeszcze nie istnieją)?Odpowiednia specyfikacja dla PUT i POST to RFC 2616 §9.5ff.
POST tworzy zasób podrzędny , więc POST
/items
tworzy zasoby znajdujące się pod/items
zasobem. Na przykład./items/1
. Dwukrotne wysłanie tego samego pakietu pocztowego spowoduje utworzenie dwóch zasobów.PUT służy do tworzenia lub zastępowania zasobu pod adresem URL znanym przez klienta .
Dlatego: PUT jest tylko kandydatem do utworzenia, w którym klient zna adres URL przed utworzeniem zasobu. Na przykład.
/blogs/nigel/entry/when_to_use_post_vs_put
ponieważ tytuł jest używany jako klucz zasobuPUT zastępuje zasób pod znanym adresem URL, jeśli już istnieje, więc dwukrotne wysłanie tego samego żądania nie przynosi żadnego efektu. Innymi słowy, połączenia do PUT są idempotentne .
RFC brzmi następująco:
Uwaga: PUT był głównie używany do aktualizacji zasobów (poprzez zastąpienie ich w całości), ale ostatnio nastąpił ruch w kierunku użycia PATCH do aktualizacji istniejących zasobów, ponieważ PUT określa, że zastępuje cały zasób. RFC 5789.
Aktualizacja 2018 : Istnieje możliwość, aby uniknąć PUT. Zobacz „REST bez PUT”
zaczerpnięte z REST API Design - Modelowanie zasobów autorstwa Prakash Subramaniam z Thoughtworks
Zmusza to interfejs API do unikania problemów ze zmianą stanu przy wielu klientach aktualizujących pojedynczy zasób i lepiej pasuje do pozyskiwania zdarzeń i CQRS. Gdy praca jest wykonywana asynchronicznie, właściwe wydaje się POST transformacji i oczekiwanie na jej zastosowanie.
źródło
Podsumowanie:
Stwórz:
Można to wykonać za pomocą PUT lub POST w następujący sposób:
Aktualizacja:
Może tylko być wykonane z PP w następujący sposób:
Wyjaśnienie:
Kiedy masz do czynienia z REST i URI jako ogólnym, masz ogólny po lewej, a konkretny po prawej . Te leki generyczne są zazwyczaj nazywane zbiory i więcej konkretnych przedmiotów można nazwać zasobem . Pamiętaj, że zasób może zawierać kolekcję .
Kiedy korzystasz z POST, zawsze masz na myśli kolekcję , więc za każdym razem, gdy mówisz:
publikujesz nowego użytkownika w kolekcji użytkowników .
Jeśli będziesz kontynuować i wypróbować coś takiego:
będzie działać, ale semantycznie mówisz, że chcesz dodać zasób do kolekcji John w ramach kolekcji użytkowników .
Kiedy używasz PUT, odnosisz się do zasobu lub pojedynczego elementu, być może wewnątrz kolekcji . Więc kiedy powiesz:
powiadamiasz o aktualizacji serwera lub utwórz, jeśli nie istnieje, zasób Johna w kolekcji użytkowników .
Specyfikacja:
Pozwól, że podkreślę kilka ważnych części specyfikacji:
POCZTA
Dlatego tworzy nowy zasób w kolekcji .
POŁOŻYĆ
Dlatego utwórz lub zaktualizuj w oparciu o istnienie zasobu .
Odniesienie:
źródło
POST
oznacza „utwórz nowy” jak w „Oto dane wejściowe do tworzenia użytkownika, utwórz go dla mnie”.PUT
oznacza „wstaw, zamień, jeśli już istnieje”, jak w „Oto dane dla użytkownika 5”.Jesteś
POST
na example.com/users, ponieważ nie znaszURL
jeszcze użytkownika, chcesz, aby serwer go utworzył.Ty
PUT
do example.com/users/id skoro chcesz wymienić / stworzenia konkretnego użytkownika.Dwukrotne wysłanie przy użyciu tych samych danych oznacza utworzenie dwóch identycznych użytkowników o różnych identyfikatorach. SKŁADANIE dwukrotnie przy użyciu tych samych danych tworzy użytkownika jako pierwszy i aktualizuje go do tego samego stanu za drugim razem (bez zmian). Ponieważ skończysz z tym samym stanem,
PUT
bez względu na to, ile razy go wykonasz, mówi się, że za każdym razem jest „równie silny” - idempotentny. Jest to przydatne do automatycznego ponawiania żądań. Nigdy więcej „czy na pewno chcesz wysłać ponownie” po naciśnięciu przycisku Wstecz w przeglądarce.Ogólna rada jest przydatna,
POST
gdy potrzebujesz, aby serwer kontrolowałURL
generowanie zasobów. UżyjPUT
inaczej. WolęPUT
ponadPOST
.źródło
user 5
jeśli jeszcze nie istnieje? Nie masz na myśliupdate, replace if already exists
? czy cośPUT
Można go również wykorzystać do zastąpienia wartości istniejącego zasobu w całości.Chciałbym dodać moją „pragmatyczną” radę. Użyj PUT, jeśli znasz „identyfikator”, przez który można zapisać zapisany obiekt. Korzystanie z PUT nie będzie działać zbyt dobrze, jeśli potrzebujesz, powiedzmy, wygenerowanego identyfikatora bazy danych, który zostanie zwrócony, abyś mógł przeprowadzić przyszłe wyszukiwania lub aktualizacje.
Zatem: Aby zapisać istniejącego użytkownika lub takiego, w którym klient generuje identyfikator i zweryfikowano, że identyfikator jest unikalny:
W przeciwnym razie użyj POST do początkowego utworzenia obiektu, a PUT do zaktualizowania obiektu:
źródło
POST /users
. (Uwaga:/users
liczba mnoga.) Ma to wpływ na utworzenie nowego użytkownika i uczynienie go podrzędnym zasobem/users
kolekcji.GET /users
ma sens, czyta tak, jak chcesz, ale byłbym w porządku z (GET /user/<id>
lubPOST /user
z ładunkiem dla wspomnianego nowego użytkownika), ponieważ poprawnie odczytuje „get me users 5” jest dziwne, ale „get me user 5” jest bardziej naturalne. Prawdopodobnie nadalUżyj POST, aby utworzyć, a PUT, aby zaktualizować. Tak zresztą Ruby on Rails to robi.
źródło
POST /items
dodaje nowy element do już zdefiniowanego zasobu („element”). Jak mówi odpowiedź, „nie tworzy grupy”. Nie rozumiem, dlaczego ma 12 głosów.PUT /items/42
to również tworzenia zasobu, ale tylko wtedy, gdy klient ma uprawnienia do nadawania nazwy zasobowi . (Czy RailsyOba są używane do transmisji danych między klientem a serwerem, ale istnieją między nimi subtelne różnice, które są:
Analogia:
Analogia mediów społecznościowych / sieci:
źródło
REST to koncepcja bardzo wysokiego poziomu. W rzeczywistości nawet nie wspomina o HTTP!
Jeśli masz wątpliwości, jak zaimplementować REST w HTTP, zawsze możesz spojrzeć na specyfikację Atom Publication Protocol (AtomPub) . AtomPub jest standardem do pisania usług internetowych RESTful z HTTP, który został opracowany przez wiele źródeł HTTP i REST, z pewnymi danymi wejściowymi od Roy Fieldinga, wynalazcy REST i (współ) wynalazcy samego HTTP.
W rzeczywistości może być nawet możliwe bezpośrednie użycie AtomPub. Wyszedł ze społeczności blogerów, ale w żaden sposób nie ogranicza się do blogowania: jest to ogólny protokół do RESTYFIKACJI interakcji z dowolnymi (zagnieżdżonymi) kolekcjami dowolnych zasobów za pośrednictwem protokołu HTTP. Jeśli możesz reprezentować swoją aplikację jako zagnieżdżoną kolekcję zasobów, możesz po prostu użyć AtomPub i nie martw się, czy użyć PUT, czy POST, jakie kody stanu HTTP zwrócić i wszystkie te szczegóły.
Oto, co AtomPub ma do powiedzenia na temat tworzenia zasobów (sekcja 9.2):
źródło
Decyzja, czy użyć PUT, czy POST do utworzenia zasobu na serwerze z interfejsem API HTTP + REST, zależy od tego, kto jest właścicielem struktury adresu URL. Poinformowanie klienta lub uczestnictwo w jego definiowaniu, struktura URL jest niepotrzebnym sprzężeniem podobnym do niepożądanych połączeń, które powstały w wyniku SOA. Unikanie rodzajów połączeń jest powodem, dla którego REST jest tak popularny. Dlatego właściwą metodą jest POST. Istnieją wyjątki od tej reguły i występują one, gdy klient chce zachować kontrolę nad strukturą lokalizacji wdrażanych zasobów. Jest to rzadkie i prawdopodobnie oznacza, że coś innego jest nie tak.
W tym momencie niektóre osoby będą argumentować, że jeśli używane są RESTful-URL , klient zna adres URL zasobu i dlatego PUT jest akceptowalny. W końcu dlatego kanoniczne, znormalizowane, Ruby on Rails, adresy URL Django są ważne, spójrz na API na Twitterze… bla bla bla. Ci ludzie muszą zrozumieć, że nie ma czegoś takiego jak Restful-URL, a sam Roy Fielding stwierdza, że :
Idea RESTful-URL jest w rzeczywistości naruszeniem REST, ponieważ serwer odpowiada za strukturę URL i powinien mieć swobodę decydowania, jak go użyć, aby uniknąć łączenia. Jeśli to dezorientuje, przeczytasz o znaczeniu samoodkrywania w projektowaniu API.
Użycie POST do tworzenia zasobów wiąże się z rozważaniami projektowymi, ponieważ POST nie jest idempotentny. Oznacza to, że kilkakrotne powtórzenie testu POST nie gwarantuje tego samego zachowania za każdym razem. To odstrasza ludzi od korzystania z PUT do tworzenia zasobów, kiedy nie powinni. Wiedzą, że to źle (POST jest dla CREATE), ale i tak to robią, ponieważ nie wiedzą, jak rozwiązać ten problem. Obawy te przejawiają się w następującej sytuacji:
Krok 6 to sytuacje, w których ludzie często mylą się co do tego, co robić. Jednak nie ma powodu, aby utworzyć kludge, aby rozwiązać ten problem. Zamiast tego można użyć protokołu HTTP, jak określono w RFC 2616, a serwer odpowiada:
Odpowiedzi z kodem statusu 409 Konflikt jest właściwym rozwiązaniem, ponieważ :
Aktualizacja oparta na wydaniu RFC 7231 na Zastąpienie 2616
RFC 7231 ma zastąpić 2616, aw sekcji 4.3.3 opisano możliwą odpowiedź dla testu POST
Może być kuszące, aby po prostu zwrócić wartość 303 w przypadku powtórzenia testu POST. Jednak prawda jest odwrotna. Zwrócenie wartości 303 miałoby sens tylko wtedy, gdy wiele żądań tworzenia (tworzenie różnych zasobów) zwróci tę samą treść. Przykładem może być „dziękuję za przesłanie wiadomości z prośbą”, której klient nie musi pobierać ponownie za każdym razem. RFC 7231 nadal utrzymuje w sekcji 4.2.2, że POST nie powinien być idempotentny i nadal utrzymuje, że POST powinien być używany do tworzenia.
Aby uzyskać więcej informacji na ten temat, przeczytaj ten artykuł .
źródło
Podoba mi się ta rada z definicji PUT w RFC 2616 :
Zastanawia się to nad inną radą, że PUT najlepiej jest stosować do zasobów, które już mają nazwę, a POST jest dobry do tworzenia nowego obiektu w ramach istniejącego zasobu (i pozwalania, aby serwer go nazwał).
Interpretuję to i wymagania idempotencji na Politechnice, co oznacza, że:
źródło
W skrócie:
PUT jest idempotentny, w którym stan zasobu będzie taki sam, jeśli ta sama operacja zostanie wykonana jeden raz lub wiele razy.
POST nie jest idempotentny, w którym stan zasobu może się różnić, jeśli operacja jest wykonywana wiele razy w porównaniu do wykonywania jednorazowego.
Analogia z zapytaniem do bazy danych
PUT Możesz pomyśleć podobnie do „UPDATE STUDENT SET address =" abc ”where id =" 123 ";
POST Możesz pomyśleć o czymś takim jak „WSTAW DO STUDENTA (nazwa, adres) WARTOŚCI („ abc ”,„ xyzzz ”);
Identyfikator studenta jest generowany automatycznie.
W przypadku PUT, jeśli to samo zapytanie jest wykonywane wielokrotnie lub jeden raz, stan tabeli STUDENT pozostaje taki sam.
W przypadku testu POST, jeśli to samo zapytanie jest wykonywane wielokrotnie, wówczas w bazie danych tworzonych jest wiele rekordów Studentów, a stan bazy danych zmienia się przy każdym wykonaniu zapytania „INSERT”.
UWAGA: PUT potrzebuje lokalizacji zasobu (już-zasobu), na której musi nastąpić aktualizacja, podczas gdy POST tego nie wymaga. Dlatego intuicyjnie test POST służy do tworzenia nowego zasobu, podczas gdy PUT jest potrzebny do aktualizacji już istniejącego zasobu.
Niektóre mogą wymyślić, że aktualizacje mogą być wykonywane za pomocą POST. Nie ma twardej reguły, której użyć do aktualizacji lub której użyć do utworzenia. Ponownie są to konwencje i intuicyjnie jestem skłonny do powyższego rozumowania i podążam za nim.
źródło
POST jest jak wysyłanie listu do skrzynki pocztowej lub wysyłanie wiadomości e-mail do kolejki e-mail. PUT jest jak umieszczenie przedmiotu w schowku lub miejscu na półce (ma znany adres).
Dzięki POST wysyłasz pocztę na adres KOLEJKI lub KOLEKCJI. Dzięki PUT podajesz adres POZYCJI.
PUT jest idempotentny. Możesz wysłać zapytanie 100 razy i to nie będzie miało znaczenia. POST nie jest idempotentny. Jeśli wyślesz zapytanie 100 razy, otrzymasz 100 e-maili lub 100 listów w swojej skrzynce pocztowej.
Ogólna zasada: jeśli znasz identyfikator lub nazwę przedmiotu, użyj PUT. Jeśli chcesz, aby identyfikator lub nazwa elementu były przypisywane przez stronę odbierającą, użyj POST.
źródło
Nowa odpowiedź (teraz, gdy lepiej rozumiem REST):
PUT jest jedynie stwierdzeniem, jakiej zawartości usługa powinna odtąd używać do renderowania reprezentacji zasobu zidentyfikowanego przez klienta; POST to stwierdzenie, jakie treści powinna odtąd zawierać usługa (być może zduplikowana), ale od serwera zależy, jak ją zidentyfikować.
PUT x
(jeślix
identyfikuje zasób ): „Zastąp zawartość zasobu wskazanego przezx
moją zawartością”.PUT x
(jeślix
nie identyfikuje zasobu): „Utwórz nowy zasób zawierający moją treść i użyj gox
do zidentyfikowania”.POST x
: „Przechowuj moją treść i podaj identyfikator, którego mogę użyć do zidentyfikowania zasobu (starego lub nowego) zawierającego tę treść (być może zmieszanego z inną treścią). Wymieniony zasób powinien być identyczny lub podporządkowany temu, któryx
identyfikuje”. „ R «a źródło jest podporządkowany x »źródło S” jest zazwyczaj, ale niekoniecznie realizowane poprzez pręd podścieżkę z X (na przykład x =/foo
i y =/foo/bar
) oraz modyfikację reprezentacji (y) x zasobów „S odzwierciedla istnienie nowego zasobu, np. z hiperłączem do yzasoby i niektóre metadane. Tylko ta ostatnia jest naprawdę niezbędna do dobrego zaprojektowania, ponieważ adresy URL są nieprzejrzyste w REST - powinieneś użyć hipermedii zamiast konstrukcji adresu URL po stronie klienta, aby przejść przez usługę.W REST nie ma czegoś takiego jak zasób zawierający „treść”. Odnoszę się do „treści” do danych, które usługa wykorzystuje do spójnego renderowania reprezentacji. Zwykle składa się z niektórych powiązanych wierszy w bazie danych lub pliku (np. Plik obrazu). Usługa polega na przekształceniu treści użytkownika w coś, z czego usługa może korzystać, np. Przekształcenie ładunku JSON w instrukcje SQL.
Oryginalna odpowiedź (może być łatwiejsza do odczytania) :
PUT /something
(jeśli/something
już istnieje): „Weź wszystko, co masz/something
i zamień to, co ci daję”.PUT /something
(jeśli jeszcze/something
nie istnieje): „Weź to, co ci daję i połóż to/something
”.POST /something
: „Weź to, co ci daję, i umieść to w dowolnym miejscu, pod/something
warunkiem, że podasz mi adres URL, gdy skończysz”.źródło
Krótka odpowiedź:
Prosta zasada: użyj POST do utworzenia, użyj PUT do aktualizacji.
Długa odpowiedź:
POCZTA:
POŁOŻYĆ:
Dłuższa odpowiedź:
Aby to zrozumieć, musimy zapytać, dlaczego PUT był wymagany, jakie problemy PUT próbował rozwiązać, czego POST nie mógł.
Z punktu widzenia architektury REST żadna nie ma znaczenia. Moglibyśmy również żyć bez PUT. Ale z punktu widzenia dewelopera klienta znacznie ułatwiło mu to życie.
Przed PUT klienci nie mogli bezpośrednio znać adresu URL wygenerowanego przez serwer ani tego, czy wszystko wygenerowało, czy też dane do wysłania na serwer są już zaktualizowane, czy nie. PUT uwolnił twórcę wszystkich tych bólów głowy. PUT jest idempotentny, PUT obsługuje warunki wyścigu, a PUT pozwala klientowi wybrać adres URL.
źródło
Ruby on Rails 4.0 użyje metody „PATCH” zamiast PUT, aby dokonać częściowych aktualizacji.
RFC 5789 mówi o PATCH (od 1995):
„ Edge Rails: PATCH to nowa podstawowa metoda HTTP do aktualizacji ” - wyjaśnia.
źródło
Ryzykując powtórzenie tego, co już powiedziano, wydaje się ważne, aby pamiętać, że PUT sugeruje, że klient kontroluje, jaki będzie adres URL podczas tworzenia zasobu. Tak więc część wyboru między PUT a POST będzie polegać na tym, na ile możesz ufać klientowi, że dostarczy prawidłowy, znormalizowany URL, który jest spójny z dowolnym schematem URL.
Jeśli nie możesz w pełni ufać klientowi, że zrobi to dobrze, lepiej byłoby użyć POST do utworzenia nowego elementu, a następnie odesłać adres URL z powrotem do klienta w odpowiedzi.
źródło
Location
nagłówka, który ma zawierać kanoniczną nazwę zasobu.PUT /X-files/series/4/episodes/max
), a serwer odpowiada URI, który zapewnia krótki kanoniczny unikalny link do tego nowego zasobu (tj./X-Ffiles/episodes/91
)W bardzo prosty sposób biorę przykład osi czasu na Facebooku.
Przypadek 1: Gdy publikujesz coś na osi czasu, jest to nowy nowy wpis. Dlatego w tym przypadku używają metody POST, ponieważ metoda POST nie jest idempotentna.
Przypadek 2: Jeśli Twój przyjaciel skomentuje Twój post po raz pierwszy, spowoduje to również utworzenie nowego wpisu w bazie danych, dzięki czemu zastosowana metoda POST.
Przypadek 3: Jeśli twój przyjaciel edytuje swój komentarz, w tym przypadku miał identyfikator komentarza, więc zaktualizuje istniejący komentarz zamiast tworzyć nowy wpis w bazie danych. Dlatego do tego typu operacji używaj metody PUT, ponieważ jest idempotentna. *
W jednym wierszu użyj POST, aby dodać nowy wpis do bazy danych, i PUT, aby zaktualizować coś w bazie danych.
źródło
Najważniejszą kwestią jest niezawodność . W przypadku zagubienia komunikatu POST stan systemu jest niezdefiniowany. Automatyczne odzyskiwanie jest niemożliwe. W przypadku komunikatów PUT stan jest niezdefiniowany tylko do pierwszej pomyślnej ponownej próby.
Na przykład tworzenie transakcji kartami kredytowymi za pomocą POST może nie być dobrym pomysłem.
Jeśli zdarzy się, że masz automatycznie wygenerowane URI w twoim zasobie, możesz nadal używać PUT, przekazując wygenerowany URI (wskazując na pusty zasób) do klienta.
Inne uwagi:
źródło
Czytelnicy, którzy nie znają tego tematu, będą poruszeni niekończącą się dyskusją na temat tego, co powinieneś zrobić, oraz względnym brakiem lekcji z doświadczenia. Fakt, że REST jest „preferowany” w stosunku do SOAP, jest, jak sądzę, uczeniem się na wysokim poziomie z doświadczenia, ale dobroć musieliśmy stamtąd rozwijać? Jest rok 2016. Praca doktorska Roya miała miejsce w 2000 roku. Co opracowaliśmy? Fajnie było? Czy łatwo było się zintegrować? Wspierać? Czy poradzi sobie ze wzrostem liczby smartfonów i niestabilnych połączeń mobilnych?
Według ME rzeczywiste sieci są zawodne. Upłynął limit czasu żądania. Połączenia są resetowane. Sieci przestają działać na kilka godzin lub dni na raz. Pociągi jeżdżą do tuneli z użytkownikami mobilnymi na pokładzie. W przypadku każdej prośby (co czasami potwierdzane w całej tej dyskusji) prośba może wpaść do wody na swojej drodze lub odpowiedź może spaść do wody w drodze powrotnej. W tych warunkach wysyłanie żądań PUT, POST i DELETE bezpośrednio do zasobów materialnych zawsze wydawało mi się trochę brutalne i naiwne.
HTTP nie robi nic, aby zapewnić niezawodne zakończenie odpowiedzi na żądanie, i jest w porządku, ponieważ jest to właściwie zadanie aplikacji obsługujących sieć. Opracowując taką aplikację, możesz przeskakiwać przez obręcze, aby użyć PUT zamiast POST, a następnie więcej obręczy, aby dać pewien rodzaj błędu na serwerze, jeśli wykryjesz duplikaty żądań. Po powrocie do klienta musisz przeskoczyć przez obręcze, aby zinterpretować te błędy, ponownie pobrać, zweryfikować ponownie i opublikować ponownie.
Lub możesz to zrobić : rozważ swoje niebezpieczne żądania jako efemeryczne zasoby dla pojedynczego użytkownika (nazwijmy je akcjami). Klienci żądają nowej „akcji” w odniesieniu do zasobu merytorycznego z pustym testem POST do zasobu. POST będzie używany tylko do tego. Po bezpiecznym posiadaniu identyfikatora URI świeżo wybitej akcji klient umieszcza niebezpieczne żądanie do identyfikatora URI akcji, a nie zasobu docelowego . Rozwiązanie akcji i aktualizacja „prawdziwego” zasobu jest właściwie zadaniem twojego API i jest tutaj oddzielona od niewiarygodnej sieci.
Serwer zajmuje się biznesem, zwraca odpowiedź i przechowuje ją w stosunku do uzgodnionego URI akcji . Jeśli coś pójdzie nie tak, klient powtarza żądanie (naturalne zachowanie!), A jeśli serwer już to widział, powtarza zapisaną odpowiedź i nic więcej nie robi .
Szybko zauważysz podobieństwo dzięki obietnicom: tworzymy i zwracamy symbol zastępczy wyniku, zanim cokolwiek zrobisz. Podobnie jak obietnica, akcja może zakończyć się sukcesem lub porażką, ale jej wynik można wielokrotnie pobrać.
Co najlepsze, dajemy aplikacjom wysyłającym i odbierającym możliwość połączenia jednoznacznie zidentyfikowanej akcji z unikalnością w ich odpowiednich środowiskach. I możemy zacząć żądać i egzekwować !, odpowiedzialne zachowanie od klientów: powtarzaj swoje prośby tak, jak chcesz, ale nie generuj nowej akcji, dopóki nie uzyskasz ostatecznego wyniku z istniejącej.
Jako takie znikają liczne kolczaste problemy. Powtarzane żądania wstawiania nie utworzą duplikatów i nie tworzymy prawdziwego zasobu, dopóki nie będziemy w posiadaniu danych. (kolumny bazy danych mogą nie być zerowalne). Powtarzane żądania aktualizacji nie trafią w niezgodne stany i nie zastąpią kolejnych zmian. Klienci mogą (ponownie) pobierać i bezproblemowo przetwarzać oryginalne potwierdzenie z dowolnego powodu (klient się zawiesił, brakowało odpowiedzi itp.).
Kolejne żądania usunięcia mogą wyświetlać i przetwarzać oryginalne potwierdzenie, nie popełniając błędu 404. Jeśli zajmie to więcej czasu niż oczekiwano, możemy tymczasowo odpowiedzieć i mamy miejsce, w którym klient może sprawdzić ostateczny wynik. Najładniejszą częścią tego wzoru jest jego właściwość Kung-Fu (Panda). Bierzemy słabość, skłonność klientów do powtarzania zapytania za każdym razem, gdy nie rozumieją odpowiedzi, i przekształcania go w siłę :-)
Zanim powiesz mi, że to nie jest RESTful, proszę rozważyć liczne sposoby przestrzegania zasad REST. Klienci nie konstruują adresów URL. Interfejs API pozostaje wykrywalny, choć z niewielką zmianą semantyki. Czasowniki HTTP są używane odpowiednio. Jeśli uważasz, że jest to ogromna zmiana do wdrożenia, z doświadczenia mogę powiedzieć, że tak nie jest.
Jeśli uważasz, że będziesz mieć do przechowywania ogromne ilości danych, porozmawiajmy o objętościach: typowe potwierdzenie aktualizacji to ułamek kilobajta. HTTP daje obecnie minutę lub dwie na ostateczną odpowiedź. Nawet jeśli przechowujesz działania tylko przez tydzień, klienci mają dużą szansę na nadrobienie zaległości. Jeśli masz bardzo duże woluminy, możesz potrzebować dedykowanego magazynu wartości klucza zgodnego z kwasem lub rozwiązania w pamięci.
źródło
Oprócz różnic sugerowanych przez innych, chcę dodać jeszcze jeden.
W metodzie POST możesz wysyłać parametry ciała
form-data
W metodzie PUT musisz wysłać parametry ciała
x-www-form-urlencoded
nagłówek
Content-Type:application/x-www-form-urlencoded
Zgodnie z tym nie można wysyłać plików ani danych wieloczęściowych metodą PUT
EDYTOWAĆ
Co oznacza, że musisz przesłać
powinieneś użyć metody POST
źródło
Wydaje się, że zawsze istnieje pewne zamieszanie co do tego, kiedy używać metody HTTP POST w porównaniu z metodą HTTP PUT dla usług REST. Większość programistów spróbuje powiązać operacje CRUD bezpośrednio z metodami HTTP. Będę argumentować, że nie jest to poprawne i nie można po prostu powiązać koncepcji CRUD z metodami HTTP. To jest:
Prawdą jest, że R (etrieve) i D (elete) operacji CRUD można odwzorować bezpośrednio na metody HTTP odpowiednio GET i DELETE. Jednak zamieszanie polega na operacjach C (reate) i U (update). W niektórych przypadkach można użyć PUT do utworzenia, podczas gdy w innych przypadkach wymagany będzie test POST. Niejednoznaczność polega na definicji metody HTTP PUT w porównaniu z metodą HTTP POST.
Zgodnie ze specyfikacjami HTTP 1.1 metody GET, HEAD, DELETE i PUT muszą być idempotentne, a metoda POST nie jest idempotentna. To znaczy, że operacja jest idempotentna, jeśli można ją wykonać na zasobie raz lub wiele razy i zawsze zwraca ten sam stan tego zasobu. Natomiast nie idempotentna operacja może zwrócić zmodyfikowany stan zasobu z jednego żądania do drugiego. Dlatego w nie idempotentnej operacji nie ma gwarancji, że ktoś otrzyma taki sam stan zasobu.
Opierając się na powyższej idempotentnej definicji, moje podejście do używania metody HTTP PUT w porównaniu do metody HTTP POST dla usług REST jest następujące: Użyj metody HTTP PUT, gdy:
W obu przypadkach operacje te można wykonać wiele razy z tymi samymi wynikami. Oznacza to, że zasób nie zostanie zmieniony poprzez żądanie operacji więcej niż raz. Stąd prawdziwa idempotentna operacja. Użyj metody HTTP POST, gdy:
Wniosek
Nie należy bezpośrednio korelować i mapować operacji CRUD na metody HTTP dla usług REST. Zastosowanie metody HTTP PUT w porównaniu z metodą HTTP POST powinno opierać się na idempotentnym aspekcie tej operacji. Oznacza to, że jeśli operacja jest idempotentna, użyj metody HTTP PUT. Jeśli operacja nie jest idempotentna, użyj metody HTTP POST.
źródło
Więc używasz POST i prawdopodobnie, ale niekoniecznie PUT do tworzenia zasobów. Nie musisz wspierać obu. Dla mnie POST jest całkowicie wystarczający. Jest to więc decyzja projektowa.
Jak wspomniałem w swoim cytacie, używasz PUT do tworzenia, że do IRI nie jest przypisany żaden zasób, a mimo to chcesz utworzyć zasób. Na przykład
PUT /users/123/password
zwykle zastępuje stare hasło nowym, ale można go użyć do utworzenia hasła, jeśli jeszcze nie istnieje (na przykład przez świeżo zarejestrowanych użytkowników lub przez przywrócenie zablokowanych użytkowników).źródło
Wyląduję z następującymi:
PUT odnosi się do zasobu identyfikowanego przez URI. W takim przypadku aktualizujesz go. Jest to część trzech czasowników odnoszących się do zasobów - usuń i zdobądź pozostałe dwa.
POST jest zasadniczo komunikatem o dowolnej formie, którego znaczenie definiuje się jako „poza pasmem”. Jeśli wiadomość można interpretować jako dodawanie zasobu do katalogu, byłoby to w porządku, ale w zasadzie musisz zrozumieć wysyłaną wiadomość (publikowanie), aby wiedzieć, co się stanie z zasobem.
Ponieważ PUT oraz GET i DELETE odnoszą się do zasobu, z definicji są również idempotentne.
POST może wykonywać pozostałe trzy funkcje, ale wówczas semantyka żądania zostanie utracona na pośrednikach, takich jak pamięci podręczne i serwery proxy. Dotyczy to również zapewnienia bezpieczeństwa zasobu, ponieważ identyfikator URI postu niekoniecznie wskazuje zasób, do którego się stosuje (może jednak).
PUT nie musi być kreacją; usługa może popełnić błąd, jeśli zasób nie został jeszcze utworzony, ale w przeciwnym razie zaktualizuj go. Lub odwrotnie - może tworzyć zasób, ale nie zezwalać na aktualizacje. Jedyną rzeczą wymaganą w PUT jest to, że wskazuje on na konkretny zasób, a jego ładunek stanowi reprezentacja tego zasobu. Udany test PUT oznacza (z wyłączeniem interferencji), że GET odzyska ten sam zasób.
Edycja: Jeszcze jedno - PUT może utworzyć, ale jeśli tak, to identyfikator musi być identyfikatorem naturalnym - AKA to adres e-mail. W ten sposób, kiedy wkładasz dwa razy, drugie wprowadzenie jest aktualizacją pierwszego. To czyni go idempotentnym .
Jeśli identyfikator zostanie wygenerowany (na przykład nowy identyfikator pracownika), wówczas drugi PUT z tym samym adresem URL utworzy nowy rekord, co narusza zasadę idempotent. W tym przypadku czasownikiem będzie POST, a komunikat (nie zasób) miałby utworzyć zasób przy użyciu wartości zdefiniowanych w tym komunikacie.
źródło
Semantyka powinna być inna, pod tym względem, że „PUT”, podobnie jak „GET”, ma być idempotentny - co oznacza, że możesz dokładnie tyle samo żądań PUT, a wynik będzie taki, jakbyś wykonał je tylko raz.
Opiszę konwencje, które moim zdaniem są najczęściej stosowane i są najbardziej przydatne:
Kiedy umieszczasz zasób pod określonym adresem URL, dzieje się tak, że powinien on zostać zapisany pod tym adresem URL lub coś w tym stylu.
Podczas wysyłania do zasobu pod określonym adresem URL często publikujesz powiązaną informację pod tym adresem URL. Oznacza to, że zasób pod adresem URL już istnieje.
Na przykład, jeśli chcesz utworzyć nowy strumień, możesz umieścić go pod jakimś adresem URL. Ale jeśli chcesz wysłać wiadomość do istniejącego strumienia, możesz wysłać wiadomość do jej adresu URL.
Jeśli chodzi o modyfikowanie właściwości strumienia, możesz to zrobić za pomocą PUT lub POST. Zasadniczo używaj „PUT” tylko wtedy, gdy operacja jest idempotentna - w przeciwnym razie użyj POST.
Należy jednak pamiętać, że nie wszystkie współczesne przeglądarki obsługują czasowniki HTTP inne niż GET lub POST.
źródło
Przez większość czasu będziesz używać ich w następujący sposób:
Na przykład:
W obu przypadkach treść żądania zawiera dane dotyczące zasobu, który ma zostać utworzony lub zaktualizowany. Z nazw tras powinno być oczywiste, że test POST nie jest idempotentny (jeśli wywołasz go 3 razy, utworzą 3 obiekty), ale PUT jest idempotentny (jeśli wywołasz go 3 razy, wynik będzie taki sam). PUT jest często używany do operacji „upsert” (tworzenie lub aktualizacja), ale zawsze możesz zwrócić błąd 404, jeśli chcesz go użyć tylko do modyfikacji.
Zauważ, że POST „tworzy” nowy element w kolekcji, a PUT „zastępuje” element pod danym adresem URL, ale bardzo powszechną praktyką jest stosowanie PUT do częściowych modyfikacji, tj. Używanie go tylko do aktualizacji istniejących zasobów i modyfikuj tylko zawarte pola w treści (ignorując inne pola). Jest to technicznie niepoprawne, jeśli chcesz być purystą REST, PUT powinien zastąpić cały zasób i powinieneś użyć PATCH do częściowej aktualizacji. Osobiście nie dbam o to, o ile zachowanie jest jasne i spójne we wszystkich punktach końcowych interfejsu API.
Pamiętaj, że REST to zestaw konwencji i wytycznych, które upraszczają interfejs API. Jeśli skończysz na skomplikowanym obejściu, aby tylko zaznaczyć pole „RESTfull”, to pokonujesz cel;)
źródło
Chociaż istnieje prawdopodobnie agnostyczny sposób ich opisania, wydaje się, że jest sprzeczny z różnymi stwierdzeniami z odpowiedzi na strony internetowe.
Bądźmy tutaj bardzo klarowni i bezpośredni. Jeśli jesteś programistą .NET pracującym z interfejsem API sieci Web, fakty są (z dokumentacji interfejsu API Microsoft), http://www.asp.net/web-api/overview/creating-web-apis/creating-a-web -api-that-wspiera-operacje-crud :
Jasne, że „możesz” użyć „POST” do aktualizacji, ale postępuj zgodnie z konwencjami określonymi dla danego frameworka. W moim przypadku jest to .NET / Web API, więc PUT jest na UPDATE, nie ma debaty.
Mam nadzieję, że pomoże to wszystkim programistom Microsoft, którzy czytają wszystkie komentarze z linkami do witryn Amazon i Sun / Java.
źródło
Oto prosta zasada:
PUT do adresu URL należy użyć do aktualizacji lub utworzenia zasobu, który może znajdować się pod tym adresem URL.
POST do adresu URL należy użyć do aktualizacji lub utworzenia zasobu, który znajduje się pod innym („podrzędnym”) adresem URL lub którego nie można zlokalizować przez HTTP.
źródło
Jeśli znasz operacje na bazie danych, istnieją
Używam
PUT
do scalania i aktualizuję podobne operacje i używamPOST
do wstawiania.źródło
W praktyce POST działa dobrze przy tworzeniu zasobów. Adres URL nowo utworzonego zasobu powinien zostać zwrócony w nagłówku odpowiedzi Lokalizacja. PUT powinien być używany do całkowitej aktualizacji zasobu. Proszę zrozumieć, że są to najlepsze praktyki podczas projektowania interfejsu API RESTful. Specyfikacja HTTP jako taka nie ogranicza użycia PUT / POST z kilkoma ograniczeniami dotyczącymi tworzenia / aktualizowania zasobów. Spójrz na http://techoctave.com/c7/posts/71-twitter-rest-api-dissected, który podsumowuje najlepsze praktyki.
źródło