Jeśli operacja RESTful PUT zwróci coś


437

Zastanawiałem się, jakie są opinie ludzi na temat PUToperacji RESTful , która nie zwraca nic (zero) w treści odpowiedzi.

Odpowiedzi:


614

Specyfikacja HTTP ( RFC 2616 ) zawiera szereg odpowiednich zaleceń. Oto moja interpretacja:

  • Kod statusu HTTP 200 OKdla udanego PUT aktualizacji istniejącego zasobu. Nie wymaga odpowiedzi. (Per sekcji 9.6 , 204 No Contentjest nawet bardziej odpowiednie).
  • Kod statusu HTTP 201 Createdudanego PUT nowego zasobu, z najbardziej szczegółowym identyfikatorem URI dla nowego zasobu zwróconym w polu nagłówka Lokalizacja oraz wszelkimi innymi istotnymi identyfikatorami URI i metadanymi zasobu, które są powtarzane w treści odpowiedzi. ( RFC 2616 sekcja 10.2.2 )
  • Kod stanu HTTP 409 Conflictdla PUT, że nie powiedzie się ze względu na 3 -cim modyfikacji -party, z listą różnic między próbą aktualizacji i aktualnego zasobu w organizmie reakcji. ( RFC 2616 sekcja 10.4.10 )
  • Kod stanu HTTP 400 Bad Requestdla nieudanego testu PUT z tekstem w języku naturalnym (takim jak angielski) w treści odpowiedzi, który wyjaśnia, dlaczego test PUT nie powiódł się. ( RFC 2616 sekcja 10.4 )

25
@stian Ciekawe! To wydaje się dość zarozumiałe ze strony Mozilli, ponieważ nie mogę znaleźć niczego w RFC 2616 (zwłaszcza sekcje 10.2 Udane 2xx i 10.2.1 200 OK ), które wyraźnie wykluczają użycie 200PUT, DELETE lub jakiejkolwiek innej metody. Przegapiłem coś? Takich jak Mozilla zostaje szefem W3 i IETF? ;) A może po prostu nigdy nie słyszeli o zasadzie solidności Postela.
system PAUZA

52
@stian: To zdanie zostało usunięte 3 lutego 2013 r. Prawdopodobnie dlatego, że ktoś o nim przeczytał tutaj. ;) developer.mozilla.org/en-US/docs/HTTP/…
Christian Strempfer

6
Semantyka metody PUT polega na zignorowaniu obecnego stanu zasobu, dlatego zwrócenie konfliktu 409 dla PUT, który nie powiódł się z powodu modyfikacji strony trzeciej, ma sens tylko wtedy, gdy żądanie jest warunkowe.
Pedro Werneck,

8
@systemPAUSE Ładna odpowiedź. Jedna mała kwestia: jeśli nie zamierzasz zwracać ciała odpowiedzi na udaną operację, sugerowałbym użycie wyłącznie 204. Niektórzy klienci (na przykład jQuery Ajax) będą się dusić, jeśli oczekują odpowiedzi o niezerowej długości, ale jej nie dostają. Możesz zobaczyć przykład tego w tym pytaniu .
nick_w

3
Prawdopodobnie RFC2616 został zaktualizowany, ponieważ udzielono na nie odpowiedzi. Nie, gdzie w 9.6 nie wspomina się No response body neededw odniesieniu do 200. W rzeczywistości ciało odpowiedzi w ogóle nie jest wymienione w odniesieniu do PUT. To tylko stwierdzaIf an existing resource is modified, either the 200 (OK) or 204 (No Content) response codes SHOULD be sent to indicate successful completion of the request.
James

164

W przeciwieństwie do większości odpowiedzi tutaj, myślę, że PUT powinien zwrócić zaktualizowany zasób (oprócz kodu HTTP oczywiście).

Powodem, dla którego chcesz zwrócić zasób jako odpowiedź na operację PUT, jest to, że gdy wysyłasz reprezentację zasobu do serwera, serwer może również zastosować pewne przetwarzanie do tego zasobu, więc klient chciałby wiedzieć, w jaki sposób ten zasób wyglądają jak po pomyślnym zakończeniu żądania. (w przeciwnym razie będzie musiał wydać kolejne żądanie GET).


3
„serwer może również zastosować pewne przetwarzanie do tego zasobu”: jestem nowy. Czy to naprawdę RESTful?
Raedwald

22
@ Raedwald na pewno tak. Usługa REST nie wymaga aktualizacji całego zasobu na stanowisku PUT, chociaż jest to ogólnie zalecane. Na przykład niektóre pola mogą nie mieć sensu aktualizować - data utworzenia lub data ostatniej modyfikacji, prawdopodobnie nie powinny być zawarte w treści PUT, ale prawdopodobnie zostałyby zmienione w wyniku PUT. To powiedziawszy, nie zgadzam się z LiorH, że PUT powinien spowodować zwrot zasobów; Potrzebuję GET po PUT, aby uzyskać zaktualizowany zasób.
Randolpho,

19
@ Randolpho REST nie wymaga, aby cały zasób był aktualizowany na PUT, czy nie powinno tak być w przypadku PATCH?
Marco Ciambrone

14
@MarcoCiambrone Tak, zgadzam się i odwołuję mój poprzedni komentarz. Zmieniłem melodię w REST i PUT - PUT powinien zawsze być idempotentny i nigdy nie powinien być używany do częściowej aktualizacji. POST jest jedyną alternatywą, chyba że PATCH jest obsługiwany, w którym to przypadku PATCH może być dobrą alternatywą. PATCH jest jednak nowym czasownikiem i może nie być obsługiwany przez niektóre frameworki po stronie serwera.
Randolpho

2
Odpowiedź została napisana na długo przed rfc7231, ale sekcja 4.3.4 wyjaśnia: „Metoda PUT wymaga utworzenia stanu zasobu docelowego lub zastąpienia go stanem zdefiniowanym przez reprezentację zawartą w ładunku komunikatu żądania”
aaaaaa

3

Myślę, że serwer może zwrócić treść w odpowiedzi na PUT. Jeśli używasz formatu obwiedni odpowiedzi, który pozwala na ładowanie danych z boku (na przykład format zużywany przez ember-data), możesz również uwzględnić inne obiekty, które mogły zostać zmodyfikowane za pomocą wyzwalaczy bazy danych itp. (Dane z ładowaniem bocznym mają wyraźnie na celu zmniejszenie Liczba żądań, a to wydaje się być dobrym miejscem do optymalizacji).

Jeśli akceptuję PUT i nie mam nic do zgłoszenia, używam kodu statusu 204 bez treści. Jeśli mam coś do zgłoszenia, używam kodu stanu 200 i dołączam ciało.


2

Specyfikacja HTTP / 1.1 (sekcja 9.6) omawia odpowiednie kody odpowiedzi / błędów. Nie dotyczy to jednak treści odpowiedzi.

Czego byś oczekiwał Prosty kod odpowiedzi HTTP (200 itd.) Wydaje mi się prosty i jednoznaczny.


Tak, ale co jeśli chcesz sprawdzić, czy wstawione dane do db po PUT lub POST naprawdę reprezentują prawdziwe dane, których potrzebujesz. Byłoby lepiej, gdyby HTTP mógł odesłać treść odpowiedzi.
tnkh

1
@ tnkh to, co sugerujesz, jest wręcz okropnym pomysłem. Wykonaj osobne połączenie GET po udanej aktualizacji, aby osiągnąć to, czego chcesz. Aby zapewnić wydajność, wprowadź warstwę buforowania, jeśli napotykasz problemy w tym dziale. Nie możemy rozwiązać tych problemów, bawiąc się logiką typu „wszystko idzie”. Nie zadzieraj z „solidnymi” i podstawowymi zasadami programowania, które powinny być rozsądne w roku 2020. To hańba!
XDS

@XDS Potwierdzam twoją pierwszą część komentarza. Ale potem nie mogę przestać przewracać oczami. Zabawny komentarz
tnkh

Dziękujemy za wyjaśnienie, dlaczego uważasz to za zabawne.
XDS,

2

Jeśli zapleczem interfejsu API REST jest relacyjna baza danych SQL, to

  1. powinieneś mieć RowVersion w każdym rekordzie, który można zaktualizować (aby uniknąć problemu z utraconą aktualizacją )
  2. zawsze powinieneś zwrócić nową kopię rekordu po PUT (aby uzyskać nową RowVersion ).

Jeśli nie przejmujesz się utraconymi aktualizacjami lub jeśli chcesz zmusić swoich klientów do wykonania GET natychmiast po PUT, nie zwracaj niczego z PUT.


1

Kod odpowiedzi 201 dla „Utworzono” wraz z nagłówkiem „Lokalizacja”, aby wskazać, gdzie klient może znaleźć nowo utworzony zasób.


5
Obiekty PUT nie są (lub nie powinny być) nowo tworzonymi zasobami
kdazzle,

9
@kdazzle PUT może z pewnością być nowo utworzonym zasobem i często nim będzie. w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6
Charlie Schliesser

3
Żeby trochę lepiej wyjaśnić mój komentarz. PUT oznacza, umieść ten przedmiot w tej konkretnej lokalizacji, zastępując to, co jest obecnie (jeśli dotyczy).
user1751825

3
Racja, „zastąpienie tego, co jest obecnie” jest kluczowym zwrotem. Powinien już istnieć i jest zastępowany. PUT nie powinien być przeznaczony do tworzenia nowych zasobów.
Kevin M

3
@KevinM Podobnie jak w najnowszym dokumencie RFC rfc7231 w dokumencie RFC, napisano , że można tworzyć zasoby: „Metoda PUT wymaga utworzenia lub zastąpienia stanu zasobu docelowego [...]” oraz powodu, dla którego myślisz, że PUT nie może utworzyć nowy zasób wynika z tego, że niekoniecznie znasz lokalizację nowego zasobu. Ale jeśli znasz jego lokalizację / identyfikator, można go utworzyć, jeśli jeszcze go nie ma.
Leo Lei

0

Użyłem RESTful API w moich usługach i oto moja opinia: Najpierw musimy przejść do wspólnego widoku :PUTsłuży do aktualizacji zasobu, którego nie można utworzyć ani uzyskać.

Zdefiniowałem zasoby za pomocą: Stateless resourcei Stateful resource:

  • Zasoby bezstanowe W przypadku tych zasobów wystarczy zwrócić kod HttpCode z pustym ciałem, wystarczy.

  • Zasoby stanowe Na przykład: wersja zasobu. W przypadku tego rodzaju zasobów musisz podać wersję, gdy chcesz ją zmienić, więc zwróć pełny zasób lub zwróć wersję klientowi, aby klient nie musiał wysyłać żądania get po aktualizacji.

Ale , na usługi lub systemu, zachować to simple, clearly, easy to use and maintainjest najważniejszą rzeczą.


6
„PUT służy do aktualizacji zasobu, którego nie można utworzyć ani uzyskać.” - to nie jest prawda ani powszechne. Według specyfikacji PUT może utworzyć zasób. Wyczyść = zgodnie z powszechnie znaną specyfikacją.
Imre Pühvel

-3

Podobnie jak pusta treść żądania jest zgodna z pierwotnym celem żądania GET, a pusta treść odpowiedzi jest zgodna z pierwotnym celem żądania PUT.


-3

wydaje się ok ... choć sądzę, że szczątkowy wskaźnik sukcesu / niepowodzenia / opublikowanego czasu / odebranych bajtów / etc. byłoby lepiej.

edycja: Myślałem zgodnie z zasadą integralności danych i / lub prowadzenia dokumentacji; metadane, takie jak skrót MD5 lub znacznik czasu dla odebranego czasu, mogą być pomocne w przypadku dużych plików danych.


1
Co powiesz na około 200 OK w nagłówku odpowiedzi statusu? Czy uważasz, że to wystarczy, by powiedzieć: „Dobrze działało dzięki?”
AnthonyWJones

nagłówek odpowiedzi zawierałby kod statusu, i tak, mówimy w tym momencie o HTTP :)
AwkwardCoder

-4

Idealnie byłoby zwrócić odpowiedź sukces / porażka.


13
Jednak nie w treści odpowiedzi. Kod statusu HTTP jest do tego miejscem. Może jeśli wystąpi błąd, niektóre informacje o rozszerzonym błędzie mogą zostać zwrócone w odpowiedzi na bidy
Archetypal Paul

-4

Istnieje różnica między nagłówkiem a treścią odpowiedzi HTTP. PUT nigdy nie powinien zwracać treści, ale musi zwracać kod odpowiedzi w nagłówku. Wybierz 200, jeśli się powiedzie, i 4xx, jeśli nie. Nie ma czegoś takiego jak zerowy kod powrotu. Dlaczego chcesz to zrobić?

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.