Czy treść jednostki jest dozwolona dla żądania HTTP DELETE?
717
Wydając żądanie HTTP DELETE, identyfikator URI żądania powinien całkowicie zidentyfikować zasób do usunięcia. Czy można jednak dodawać dodatkowe metadane jako część treści żądania?
W ASP.NET WebApi 2 FromBody Parametry są ignorowane dla punktów końcowych HttpDelete.
Jenny O'Reilly,
2
Mam podobne obawy, ale moja sprawa jest inna. Chcę wysłać żądanie usunięcia partii, gdy chcę usunąć sto obiektów. Z pewnością jest to świetny wzrost wydajności dla sieci starszych niż HTTP 2.0.
Singagirl,
1
Czy były jakieś zmiany w HTTP / 2?
Jyotman Singh
Odpowiedzi:
570
Specyfikacja nie zabrania tego wyraźnie ani nie zniechęca, więc powiedziałbym, że jest dozwolony.
@Jason Zdecydowanie. Możesz również użyć niestandardowych nagłówków, aby przekazać dodatkowe dane, ale dlaczego nie użyć treści żądania.
Tomalak
86
Chociaż specyfikacja nie zabrania żądania DELETE posiadania treści komunikatu, sekcja 4.3 wydaje się wskazywać, że treść powinna być ignorowana przez serwery, ponieważ nie ma „zdefiniowanej semantyki” dla DELETE -treści: „Serwer POWINIEN odczytać i przekazać treść wiadomości na każde żądanie; jeśli metoda żądania nie zawiera zdefiniowanej semantyki dla ciała encji, wówczas treść wiadomości POWINNA zostać zignorowana podczas obsługi żądania . "
Shelley,
72
Należy pamiętać, że wielu klientów nie może również wysłać USUŃ z treścią. To właśnie spaliło mnie na Androida.
Dużo dyskusji na temat implementacji zmieszanych ze specyfikacją HTTP. Klienci będą wdrażać rzeczy w sposób, w jaki interpretują specyfikację, nie myl tego z jej znaczeniem. Faktem jest, że specyfikacja pozostawia to niejednoznaczne. Nie zgadzam się z interpretacją, że ponieważ nie ma zdefiniowanej semantyczności dla ciała-istoty, istnieje implikacja, że należy ją zignorować. Myślę, że ludzie pracują wstecz od istniejących interpretacji klientów (Jersey, klienci testowi na Androida itp.) I próbują uzasadnić interpretację, zamiast starać się być wiernym specyfikacji. Ludzie są omylni.
Gibron
169
Najnowsza aktualizacja specyfikacji HTTP 1.1 ( RFC 7231 ) wyraźnie zezwala na treść jednostki w żądaniu DELETE:
Ładunek w komunikacie żądania DELETE nie ma zdefiniowanej semantyki; wysłanie treści ładunku na żądanie DELETE może spowodować, że niektóre istniejące implementacje odrzucą żądanie.
najnowsza niezatwierdzona wersja specyfikacji usuwa to wymaganie. Ostatnia zatwierdzona wersja to wciąż RFC2616 cytowany powyżej.
BishopZ
4
Która wersja Wersja 20 nadal ma to samo brzmienie, co wersja 19, do której odsyłam powyżej: „Organy żądań DELETE nie mają zdefiniowanej semantyki. Pamiętaj, że wysłanie treści na żądanie DELETE może spowodować, że niektóre istniejące implementacje odrzucą żądanie”.
grzes
11
Sugestie w wersji 26, na które możesz zezwolić na treść: zawiera A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.więc ostrzeżenie o zgodności z poprzednimi wersjami, sugeruje, że następny standard będzie brzmiał: „tak! DELETEmoże mieć ciało`.
Pure.Krome
4
RFC 7231 sekcja 4.3.5 finalizuje język od wersji 26 z A payload within a DELETE request message has no defined semantics. Ciało jest dozwolone.
mndrix
6
Treść jest dozwolona, ale nie powinna być istotna dla żądania. Nie ma absolutnie sensu z niego korzystać.
Evert
54
Niektóre wersje Tomcat i Jetty wydają się ignorować ciało jednostki, jeśli jest obecne. Co może być uciążliwe, jeśli zamierzasz je otrzymać.
Powinieneś uzyskać optymistyczny wyjątek blokady. Ponownie przeczytaj zapis, sprawdź, czy jest ważny, a może go nie usuń.
Innym powodem korzystania z niego jest usuwanie wielu rekordów jednocześnie (na przykład siatka z polami wyboru wierszy).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Zauważ, że każda wiadomość ma swoją własną wersję. Być może możesz określić wiele wersji przy użyciu wielu nagłówków, ale George jest to prostsze i znacznie wygodniejsze.
Działa to w Tomcat (7.0.52) i Spring MVC (4.05), prawdopodobnie także we wcześniejszych wersjach:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
Posiadanie obiektów w GET (i DELETE) wyraźnie źle znosi HTTP i REST. Istnieją inne mechanizmy radzenia sobie z kontrolą współbieżności (np. If-Modified-Since i etags).
Bruno
19
W JAKI SPOSÓB JEST JEST on źle traktowany, gdy specyfikacja nie zabrania treści w USUŃ?
Jest to dokładnie ten sam problem: GET pozwala pobrać reprezentację zasobu identyfikowanego przez URI, a DELETE usuwa zasób zidentyfikowany przez URI. Użyj innego identyfikatora URI dla innych wersji, jeśli chcesz usunąć określone wersje. Identyfikator URI powinien być jedynym identyfikatorem zasobu w HTTP / REST. Użyj metadanych w nagłówkach, jeśli potrzebujesz obsługi współbieżności (np. If-Unmodified-SinceLub Etagwłaśnie do tego służą ).
Obecność treści komunikatu w żądaniu jest sygnalizowana przez włączenie pola nagłówka Content-Length lub Transfer-Encoding do nagłówków komunikatu żądania. Ciało komunikatu NIE MOŻE być zawarte w żądaniu, jeśli specyfikacja metody żądania (sekcja 5.1.1) nie pozwala na wysyłanie ciała jednostki w żądaniach. Serwer POWINIEN czytać i przekazywać treść wiadomości na każde żądanie; jeśli metoda żądania nie obejmuje zdefiniowanej semantyki dla ciała encji, wówczas treść komunikatu POWINNA zostać zignorowana podczas obsługi żądania.
I sekcja 9.7:
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 byt opisujący status, 202 (Zaakceptowana), jeśli akcja nie została jeszcze wykonana, 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 można buforować. C
Dlatego nie jest to wyraźnie dozwolone ani zabronione, a istnieje prawdopodobieństwo, że proxy po drodze usunie treść wiadomości (chociaż POWINNA ją odczytać i przekazać dalej).
Tylko jeden do góry, jeśli podasz ciało we wniosku DELETE i używasz modułu równoważenia obciążenia HTTPS w chmurze Google, odrzuci twoje żądanie z błędem 400. Uderzyłem głową w ścianę i dowiedziałem się, że Google, z jakiegokolwiek powodu, uważa, że żądanie USUŃ z ciałem jest błędnym żądaniem.
for whatever reason- ponieważ specyfikacja tak mówi: P
Mardoxx
20
Specyfikacja nie „tak mówi”, po prostu mówi, że ciało nie jest specjalnie zdefiniowane. Jeśli nie jest zdefiniowane, a chcesz to zignorować, spoko ... śmiało i zignoruj to. Ale całkowite odrzucenie wniosku wydaje się skrajne i niepotrzebne.
Ben Fried
1
Nie polegaj na niezdefiniowanym zachowaniu. To dość powszechna najlepsza praktyka.
Evert
@Evert ma jawnie niezdefiniowane zachowanie (na przykład opis w specyfikacji języka C) oraz zachowanie, które jest dozwolone, ale po prostu nieopisane. Korzystanie z treści wiadomości w DELETEtym drugim przypadku.
Alnitak
9
Warto zauważyć, że specyfikacja OpenAPI dla wersji 3.0 porzuciła obsługę metod DELETE z treścią:
Jeśli używasz klienta HTTP Apache, możesz łatwo tworzyć własne wersje GET i DELETE, rozszerzając HttpEntityEnclosingRequestBase i sprawiając, że metoda getMethod () zwraca GET lub DELETE. Używamy tego do rozmowy z elasticsearch.
Jilles van Gurp
2
martwy link - świetnie. potrzebujemy więcej tych odpowiedzi na linki - nie
cottton,
3
Powiązana dokumentacja zawiera teraz tylko żądania POST, bez usuwania. Czy warto dodać notatkę do tej odpowiedzi?
dshepherd
Elasticsearch używa również treści z żądaniami GET.
Ciało GET / DELETE jest absolutnie zabronione, aby miało jakikolwiek wpływ na przetwarzanie lub interpretację wniosku
Oznacza to, że ciało nie może modyfikować zachowania serwera. Następnie dodaje:
oprócz konieczności czytania i odrzucania odebranych bajtów w celu utrzymania ramkowania wiadomości.
I wreszcie powód, dla którego nie zabraniam ciała:
Jedynym powodem, dla którego nie zabroniliśmy wysyłania treści, jest to, że prowadziłoby to do leniwych implementacji, zakładając, że żadne ciało nie zostanie wysłane.
Podczas gdy klienci mogą wysyłać treść ładunku, serwery powinny ją upuścić, a interfejsy API nie powinny definiować semantycznej treści ładunku dla tych żądań.
Ładunek w komunikacie żądania DELETE nie ma zdefiniowanej semantyki; wysłanie treści ładunku na żądanie DELETE może spowodować, że niektóre istniejące implementacje odrzucą żądanie. https://tools.ietf.org/html/rfc7231#page-29
Użycie a POSTnie jest dobrym sposobem RESTy do tworzenia nowych zasobów, ponieważ semantyka odpowiedzi POST jest niejasna, szczególnie w kontekście nagłówków lokalizacji. Zasadniczo zostawiasz HTTP za sobą i stos RPC na wierzchu. Prawidłowym „sposobem HTTP / REST” jest tworzenie zasobów za pomocą PUTw / If-None-Match: *nagłówka (lub określanie właściwych metod HTTP, patrz MKCOLitp.).
hnh
4
Nie sądzę, aby opublikowano dobrą odpowiedź na to pytanie, chociaż na temat istniejących odpowiedzi pojawiło się wiele świetnych komentarzy. Podniosę sedno tych komentarzy do nowej odpowiedzi:
Ładunek w komunikacie żądania DELETE nie ma zdefiniowanej semantyki; wysłanie treści ładunku na żądanie DELETE może spowodować, że niektóre istniejące implementacje odrzucą żądanie.
W innych odpowiedziach brakowało mi implikacji. Tak, dozwolone jest dołączanie treści na DELETEżądanie, ale jest to semantycznie bez znaczenia. To tak naprawdę oznacza, że wydanie DELETEżądania z treścią żądania jest semantycznie równoważne z pominięciem treści żądania.
Dołączenie treści żądania nie powinno mieć żadnego wpływu na żądanie, więc włączenie go nigdy nie ma sensu.
tl; dr: Technicznie DELETEżądanie z treścią żądania jest dozwolone, ale nigdy nie jest to przydatne.
„semantycznie bez znaczenia” nie oznacza tego samego, co „nie ma zdefiniowanej semantyki”. To pierwsze oznacza, że nie może mieć żadnego znaczenia. To ostatnie oznacza po prostu, że sama RFC nie określa, czym może być ta semantyka. (Piszę RFC)
Alnitak
1
Innymi słowy, jeśli implementator API chce zdefiniować dla siebie trochę semantyki, jest to całkowicie wolny.
Alnitak
1
@Alnitak to zdecydowanie błędna interpretacja. Zgodnie z tą definicją, wszelkie treści żądania HTTP nie mają zdefiniowanej semantyki, ale DELETE i GET są specyficznie wywoływane w specyfikacji. Oto fragment z jeszcze nieopublikowanego projektu, który mówi o tym konkretnie o żądaniu GET:
Evert
1
Nie zgadzam się z tobą, że nie jest to jasne w obecnie wydanych RFC, ale jeśli mi nie wierzysz, zaprosiłbym cię, aby zapytać autorów po ich woli usunięcia i pobrania. Przekonasz się, że zgadza się z moją odpowiedzią. Podobnie jak ty, jestem również zaangażowany w prace organów normalizacyjnych i nie jestem samotną osobą, która ma opinię na temat interpretacji RFC.
Evert
2
W takim przypadku 7231 jest źle sformułowany i powinien był powiedzieć „ciało danych MUSI zostać zignorowane”. Do którego szkicu odwołujesz się powyżej?
Alnitak
3
W przypadku, gdy ktoś uruchamia się w celu przetestowania tego problemu, nie, nie jest to powszechnie obsługiwane.
Obecnie testuję z Sahi Pro i jest bardzo widoczne, że wywołanie http DELETE usuwa wszelkie dostarczone dane treści (duża lista identyfikatorów, które należy usunąć zbiorczo zgodnie z projektem punktu końcowego).
Byłem z nimi w kontakcie kilka razy, a także wysłałem w trzech osobnych paczkach skrawków, zdjęć, dzienników do przejrzenia i nadal tego nie potwierdzili. Nieudana łatka i nieodebrane połączenia konferencyjne przez ich wsparcie później, a ja wciąż nie otrzymałem solidnej odpowiedzi.
Jestem pewien, że Sahi nie obsługuje tego i wyobrażam sobie, że wiele innych narzędzi podąża za tym pakietem.
Jest zaimplementowany w najnowszej wersji Sahi Pro. Ponieważ Sahi używa Java do wykonywania połączeń HTTP, a Java miała błąd przed wersją 1.8, który nie pozwalał użytkownikowi na żądanie DELETE. Tak więc od wersji Java 1.8 i Sahi Pro 6.1.1 (wkrótce będzie dostępny publicznie) ludzie mogą wysyłać żądania DELETE z treścią w Sahi.
Vivek V Dwivedi
-1
Być może poniższy adres GitHUb pomoże ci uzyskać odpowiedź. W rzeczywistości serwer aplikacji, taki jak Tomcat, Weblogic odmawia połączenia HTTP.DELETE z ładunkiem żądania. Mając to na uwadze, dodałem przykład w github, proszę spojrzeć na to
Odpowiedzi:
Specyfikacja nie zabrania tego wyraźnie ani nie zniechęca, więc powiedziałbym, że jest dozwolony.
Microsoft widzi to w ten sam sposób (słyszę szmery na widowni), stwierdzają w artykule MSDN na temat metody DELETE ADO.NET Data Services Framework :
Dodatkowo oto, co ma do powiedzenia RFC2616 (HTTP 1.1) w odniesieniu do żądań:
Content-Length
lubTransfer-Encoding
nagłówka (sekcja 4.3)W przypadku odpowiedzi określono to:
źródło
Najnowsza aktualizacja specyfikacji HTTP 1.1 ( RFC 7231 ) wyraźnie zezwala na treść jednostki w żądaniu DELETE:
źródło
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request.
więc ostrzeżenie o zgodności z poprzednimi wersjami, sugeruje, że następny standard będzie brzmiał: „tak!DELETE
może mieć ciało`.A payload within a DELETE request message has no defined semantics
. Ciało jest dozwolone.Niektóre wersje Tomcat i Jetty wydają się ignorować ciało jednostki, jeśli jest obecne. Co może być uciążliwe, jeśli zamierzasz je otrzymać.
źródło
Jednym z powodów użycia treści w żądaniu usunięcia jest optymistyczna kontrola współbieżności.
Czytasz wersję 1 rekordu.
Twój kolega czyta wersję 1 rekordu.
Twój kolega zmienia zapis i aktualizuje bazę danych, która aktualizuje wersję do 2:
Próbujesz usunąć rekord:
Powinieneś uzyskać optymistyczny wyjątek blokady. Ponownie przeczytaj zapis, sprawdź, czy jest ważny, a może go nie usuń.
Innym powodem korzystania z niego jest usuwanie wielu rekordów jednocześnie (na przykład siatka z polami wyboru wierszy).
Zauważ, że każda wiadomość ma swoją własną wersję. Być może możesz określić wiele wersji przy użyciu wielu nagłówków, ale George jest to prostsze i znacznie wygodniejsze.
Działa to w Tomcat (7.0.52) i Spring MVC (4.05), prawdopodobnie także we wcześniejszych wersjach:
źródło
If-Unmodified-Since
LubEtag
właśnie do tego służą ).Wydaje mi się, że RFC 2616 tego nie określa.
Z sekcji 4.3:
I sekcja 9.7:
Dlatego nie jest to wyraźnie dozwolone ani zabronione, a istnieje prawdopodobieństwo, że proxy po drodze usunie treść wiadomości (chociaż POWINNA ją odczytać i przekazać dalej).
źródło
Tylko jeden do góry, jeśli podasz ciało we wniosku DELETE i używasz modułu równoważenia obciążenia HTTPS w chmurze Google, odrzuci twoje żądanie z błędem 400. Uderzyłem głową w ścianę i dowiedziałem się, że Google, z jakiegokolwiek powodu, uważa, że żądanie USUŃ z ciałem jest błędnym żądaniem.
źródło
for whatever reason
- ponieważ specyfikacja tak mówi: PDELETE
tym drugim przypadku.Warto zauważyć, że specyfikacja OpenAPI dla wersji 3.0 porzuciła obsługę metod DELETE z treścią:
patrz tutaj i tutaj dla odniesienia
Może to wpłynąć na twoją implementację, dokumentację lub korzystanie z tych interfejsów API w przyszłości.
źródło
Wygląda na to, że ElasticSearch używa tego: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
Co oznacza, że Netty to obsługuje.
Jak wspomniano w komentarzach, może już tak nie być
źródło
Roy Fielding na liście mailingowej HTTP wyjaśnia, że na liście mailingowej http https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html i mówi:
Oznacza to, że ciało nie może modyfikować zachowania serwera. Następnie dodaje:
I wreszcie powód, dla którego nie zabraniam ciała:
Podczas gdy klienci mogą wysyłać treść ładunku, serwery powinny ją upuścić, a interfejsy API nie powinny definiować semantycznej treści ładunku dla tych żądań.
źródło
Nie jest to zdefiniowane .
źródło
Używanie DELETE z treścią jest ryzykowne ... Wolę to podejście w przypadku operacji list niż REST:
Regularne operacje
GET / objects / Pobiera wszystkie obiekty
GET / object / ID Pobiera obiekt o określonym identyfikatorze
POST / objects Dodaje nowy obiekt
PUT / object / ID Dodaje obiekt o określonym identyfikatorze, aktualizuje obiekt
DELETE / object / ID Usuwa obiekt o określonym identyfikatorze
Wszystkie akcje niestandardowe są POST
POST / objects / addList Dodaje listę lub tablicę obiektów zawartych w treści
POST / objects / deleteList Usuwa listę obiektów zawartych w ciele
POST / objects / customQuery Tworzy listę na podstawie niestandardowego zapytania w treści
Jeśli klient nie obsługuje twoich rozszerzonych operacji, może działać normalnie.
źródło
POST
nie jest dobrym sposobem RESTy do tworzenia nowych zasobów, ponieważ semantyka odpowiedzi POST jest niejasna, szczególnie w kontekście nagłówków lokalizacji. Zasadniczo zostawiasz HTTP za sobą i stos RPC na wierzchu. Prawidłowym „sposobem HTTP / REST” jest tworzenie zasobów za pomocąPUT
w /If-None-Match: *
nagłówka (lub określanie właściwych metod HTTP, patrzMKCOL
itp.).Nie sądzę, aby opublikowano dobrą odpowiedź na to pytanie, chociaż na temat istniejących odpowiedzi pojawiło się wiele świetnych komentarzy. Podniosę sedno tych komentarzy do nowej odpowiedzi:
Ten akapit z RFC7231 został zacytowany kilka razy, co w sumie go podsumowuje.
W innych odpowiedziach brakowało mi implikacji. Tak, dozwolone jest dołączanie treści na
DELETE
żądanie, ale jest to semantycznie bez znaczenia. To tak naprawdę oznacza, że wydanieDELETE
żądania z treścią żądania jest semantycznie równoważne z pominięciem treści żądania.Dołączenie treści żądania nie powinno mieć żadnego wpływu na żądanie, więc włączenie go nigdy nie ma sensu.
tl; dr: Technicznie
DELETE
żądanie z treścią żądania jest dozwolone, ale nigdy nie jest to przydatne.źródło
W przypadku, gdy ktoś uruchamia się w celu przetestowania tego problemu, nie, nie jest to powszechnie obsługiwane.
Obecnie testuję z Sahi Pro i jest bardzo widoczne, że wywołanie http DELETE usuwa wszelkie dostarczone dane treści (duża lista identyfikatorów, które należy usunąć zbiorczo zgodnie z projektem punktu końcowego).
Byłem z nimi w kontakcie kilka razy, a także wysłałem w trzech osobnych paczkach skrawków, zdjęć, dzienników do przejrzenia i nadal tego nie potwierdzili. Nieudana łatka i nieodebrane połączenia konferencyjne przez ich wsparcie później, a ja wciąż nie otrzymałem solidnej odpowiedzi.
Jestem pewien, że Sahi nie obsługuje tego i wyobrażam sobie, że wiele innych narzędzi podąża za tym pakietem.
źródło
Być może poniższy adres GitHUb pomoże ci uzyskać odpowiedź. W rzeczywistości serwer aplikacji, taki jak Tomcat, Weblogic odmawia połączenia HTTP.DELETE z ładunkiem żądania. Mając to na uwadze, dodałem przykład w github, proszę spojrzeć na to
https://github.com/ashish720/spring-examples
źródło
Udało mi się zaimplementować operację DELETE z treścią żądania. Użyłem bramy AWS Lambda i AWS API i użyłem języka Go.
źródło