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.