Czy żądanie HTTP PUT musi zawierać treść?


92

Mam problem ze znalezieniem dokładnej specyfikacji tego w standardzie. Mam klienta HTTP, który nie zawiera Content-Length: 0nagłówka podczas wykonywania żądania PUT, w którym nie określam treści, oraz serwer, który jest zdezorientowany przez takie żądania i zastanawiam się, który program powinienem winić.


Dlaczego miałbyś edytować pytanie z 2009 roku, jeśli mogę o to zapytać?
zmuci

@zmuci Dla lepszego formatowania?
Константин Ван

Odpowiedzi:


83

Żądania HTTP mają treść, jeśli mają nagłówek Content-Length lub Transfer-Encoding ( RFC 2616 4.3 ). Jeśli żądanie nie zawiera żadnego z nich, nie ma treści, a serwer powinien je tak traktować.

To powiedziawszy, to niezwykłe, że żądanie PUT nie ma treści, więc gdybym projektował klienta, który naprawdę chciałby wysłać pustą treść, przekazałbym Content-Length: 0. Rzeczywiście, w zależności od odczytu POST i definicje metod PUT ( RFC 2616 9.5, 9.6 ) można by argumentować, że treść jest implikowana jako wymagana - ale rozsądnym sposobem obsługi braku treści byłoby przyjęcie treści o zerowej długości.


Zgodnie z kodami stanu HTTP 200 („OK”), 201 („Utworzono”) i 204 („Brak treści”), PUTżądanie zasadniczo służy do tworzenia lub aktualizowania pliku na serwerze. I nie ma nic nielegalnego w pustym pliku, prawda?
Константин Ван


5
@bdonlan powiedziałeś, że PUT z pustą treścią jest nietypowy, ale jeśli chcę włączyć lub wyłączyć użytkownika, nie będę potrzebował treści na moje żądanie, w rzeczywistości żądania PUT mogą mieć postać „/ users / {id} / enable” lub „/ users / {id} / disable”.
Vinicius de Almeida

@ViniciusdeAlmeida Te zasoby nie byłyby odpowiednie, jeśli starasz się przestrzegać standardów REST. disablei enablesą czasownikami. W takim przypadku prawdopodobnie wolałbym używać PATCHna /users/{id}punkcie końcowym.
zmiażdżyć

42

Nie odpowiadając na pytanie, ale stwierdzając, w jaki sposób jaxrs pozwala mi na częste używanie bezcielesnych PUTów:

Przykład umieszczania bez ciała: Nadaj użytkownikowi dodatkowe uprawnienia.

PUT / admin / users / {nazwa użytkownika} / pozwolenie / {pozwolenie}


2
Dokładnie mój problem! Doszedłem do tego samego wniosku. Ale mówiąc ściśle, jest to sprzeczne z RFC, w którym, chociaż nie zostało to wyraźnie wymienione, ciało jest określane jako istniejące. Może to powodować problemy, ale z mojego doświadczenia wynika, że ​​wszystkie nowoczesne serwery / frameworki internetowe będą działać.
Agoston Horvath

Jestem w podobnym przypadku, potrzebuję API, aby skojarzyć istniejący zasób z użytkownikiem. Mógłbym użyć POST users /: userId / resources z resourceId w treści. A raczej pasowałby do użytkowników PUT /: userid / resources /: resourceId. Duża różnica polega na tym, że pierwszy interfejs API nie powinien być idempotentny, więc mógłbym dwukrotnie skojarzyć ten sam zasób z użytkownikiem. wezwanie PUT powinno zresetować poprzednie stowarzyszenie
Carmine Ingaldi

5

Treść nie jest wymagana przez standard IETF, chociaż długość treści powinna wynosić 0, jeśli nie ma treści. Użyj metody odpowiedniej do tego, co robisz. Jeśli miałbyś umieścić to w kodzie, to podane

int x;
int f(){ return x; }

i zdalna zmienna o nazwie r.

Post jest odpowiednikiem

r=f();

Put jest równoważne

r=x;

a get jest równoważne

x=r;

1
To najwyraźniejszy przykład PUT vs POST, jaki kiedykolwiek czytałem, choć nie na temat
iluzja cyfrowa

Jeśli żądanie ma nagłówek Content-Length, to ma treść. Może to być puste ciało, ale wciąż ciało. W przeciwieństwie do żądania bez nagłówka Content-Length, które nie ma żadnej treści, nawet pustej. Więc tak, żądanie PUT, technicznie, ściśle, musi mieć treść. Zawsze.
Paul Groke

Również twoja analogia do POST jest dla mnie całkowicie myląca. Jeśli spróbuję pozostać przy reszcie twojej analogii, powinno być bardziej tak, jakby serwer miał wywołanie, int f(int* resource, int body);a następnie wywołałby POST f(&r, x);- co może zrobić lub nie zrobić rtego, co serwer uważa za stosowne. Ale może też zwrócić rzeczy, więc ... może bardziej jak y = f(&r, x);.
Paul Groke

0

Co jest umieszczane (w sensie czasownika) na serwerze, jeśli nie ma treści? Specyfikacja odnosi się do treści jako „zamkniętą jednostkę”, ale wniosek bez zawartości nie miałby zamkniętą jednostkę, a zatem nic, aby umieścić na serwerze.

O ile, oczywiście, nie chciałeś niczego WCIĄGNĄĆ na serwer, w takim przypadku prawdopodobnie wolałbyś zamiast tego DELETE.


1
to, co umieszczasz, może być zakodowane w adresie URL, a nie w treści
MikeT

1
PUT empty to po prostu deklaracja, że ​​zasób z podaną tożsamością musi istnieć na serwerze, chociaż nie ma zawartości poza samą tożsamością. To zupełnie inna semantyka od DELETE.
Imre Pühvel

Wyobraź sobie, że chcesz umieścić zasób, ale akceptujesz wszystkie wartości domyślne po stronie serwera. To byłoby Content-Length: 0lub { }w JSON jako ciało?
Luke Puplett

1
Więc nie masz ani jednego pustego pliku na swoim komputerze, prawda?
Константин Ван

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.