Varlık gövdesine HTTP DELETE isteği için izin veriliyor mu?


719

Bir HTTP DELETE isteği yayınlanırken, istek URI'sı silinecek kaynağı tamamen tanımlamalıdır. Ancak, isteğin varlık gövdesinin bir parçası olarak fazladan meta veri eklenmesine izin veriliyor mu?


4
ASP.NET WebApi 2'de HttpDelete uç noktaları için FromBody Parametreleri yoksayılır.
Jenny O'Reilly

2
Benzer bir endişem var, ama benim durumum farklı. Yüz nesneyi silmek istediğimde toplu silme isteği vermek istiyorum. Kesinlikle HTTP öncesi ağlar için büyük bir performans artışıdır.
Singagirl

1
HTTP / 2'de herhangi bir değişiklik oldu mu?
Jyotman Singh

Yanıtlar:


570

Spesifikasyon açıkça yasaklamaz veya cesaretini kırmaz, bu yüzden izin verildiğini söyleme eğilimindeyim.

Microsoft aynı şekilde görüyor (izleyicide mırıltı duyabiliyorum), onlar ADO.NET Veri Hizmetleri Çerçevesi DELETE Yöntemi hakkında MSDN makalesinde :

DELETE isteği bir varlık gövdesi içeriyorsa, gövde yok sayılır [...]

Ek olarak, RFC2616'nın (HTTP 1.1) isteklerle ilgili söyledikleri:

  • Bir işletme gövdesi bir zaman sadece mevcut olan ileti vücut mevcut olan (bölüm 7.2)
  • bir mesaj gövdesinin varlığı a Content-Lengthveya Transfer-Encodingüstbilginin eklenmesiyle bildirilir (bölüm 4.3)
  • Bir mesaj gövdesi talep yönteminin özellikleri bir gönderilmesine izin vermediğinde dahil edilmemelidir işletme gövdesi (bölüm 4.3)
  • Bir varlık-vücut açıkça TRACE yasak sadece, diğer tüm istek türleri (bölüm 9 ve 9.8 özellikle) sınırlanmayan edilir istekleri

Yanıtlar için bu tanımlanmıştır:

  • Bir olup mesaj gövdesi dahil her iki istek yöntemi bağlıdır ve karşılık statüsü (bölüm 4.3)
  • HEAD isteklerine verilen yanıtlarda bir mesaj gövdesi açıkça yasaktır (bölüm 9 ve özellikle 9.4)
  • 1xx (bilgi amaçlı), 204 (içerik yok) ve 304 (değiştirilmemiş) yanıtlarda bir ileti gövdesi açıkça yasaktır (bölüm 4.3)
  • diğer tüm yanıtlar bir ileti gövdesi içerir, ancak sıfır uzunlukta olabilir (bölüm 4.3)

7
@Jason Kesinlikle. Ek verileri iletmek için özel başlıklar da kullanabilirsiniz, ancak neden istek gövdesini kullanmıyorsunuz?
Tomalak

86
Spec, DELETE isteklerinin bir ileti gövdesine sahip olmasını yasaklamasa da, bölüm 4.3 , DELETE varlık gövdeleri için "tanımlı anlambilim" olmadığından gövdenin sunucular tarafından yoksayılması gerektiğini gösteriyor : "Bir sunucu, herhangi bir istekte ileti gövdesi; istek yöntemi bir varlık gövdesi için tanımlanmış anlambilim içermiyorsa, ileti işlenirken ileti gövdesi yok sayılmalıdır . "
shelley

72
Birçok istemcinin bir gövde ile DELETE gönderemediğini lütfen unutmayın. Bu beni Android'de yaktı.
Karmic Coder

1
@KarmicCoder: Harika bir nokta. Daha fazla bilgi: Android'de HTTP DELETE isteği gönderme .
MS Dousti

2
HTTP spec ile karışık uygulama hakkında çok sayıda tartışma. Müşteriler bir şeyi özellikleri yorumladıkları şekilde uygulayacaklar, bunu özelliklerin anlamı ile karıştırmayın. Gerçek şu ki, spec bunu belirsiz bırakıyor. Varlık-beden için tanımlanmış bir semantik olmadığından, görmezden gelinmesi gerektiği anlamına gelen bir yorum olduğu konusunda yorum yapmıyorum. Bence insanlar var olan belirli yorumlardan (Jersey, Android test istemcileri, vb.) Müşterilerden geriye doğru çalışıyorlar ve spesifikasyona sadık kalmaya çalışmak yerine yorumu haklı çıkarmaya çalışıyorlar. İnsanlar hata yapabilir.
Gibron

169

HTTP 1.1 spesifikasyonunda ( RFC 7231 ) yapılan en son güncelleme , bir DELETE isteğinde bir varlık gövdesine açıkça izin verir:

DELETE istek iletisindeki bir yükün tanımlanmış bir anlamı yoktur; bir DELETE isteği üzerine bir yük gövdesi göndermek, mevcut bazı uygulamaların isteği reddetmesine neden olabilir.


3
spesifikasyonun onaylanmamış en son sürümü bu gereksinimi ortadan kaldırır. Onaylanan en son sürüm hala yukarıda belirtilen RFC2616'dır.
BishopZ

4
Hangi versiyon? Sürüm 20, yukarıda bağladığım sürüm 19 ile aynı ifadeye sahip: "DELETE isteklerindeki gövdelerde tanımlanmış bir anlam bilgisi yoktur. DELETE isteğine bir gövde gönderilmesinin, mevcut bazı uygulamaların isteği reddetmesine neden olabileceğini unutmayın."
grzes

11
Bir gövdeye izin verebileceğiniz 26 sürüm önerileri: 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.Geriye dönük bir uyumluluk uyarısı ile birlikte gelir, bir sonraki standardın 'evet! DELETEbir vücuda sahip olabilir.
Pure.Krome

4
RFC 7231 bölüm 4.3.5 , 26 sürümünden dili sonlandırır A payload within a DELETE request message has no defined semantics. Böylece vücuda izin verilir.
17'de mndrix

6
Vücuda izin verilir, ancak istekle alakalı olmamalıdır. Kullanmanın kesinlikle bir anlamı yok.
Evert


50

Gövdeyi silme isteğinde kullanmanın bir nedeni iyimser eşzamanlılık kontrolüdür.

Bir kaydın 1. sürümünü okudunuz.

GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }

İş arkadaşınız kaydın 1. sürümünü okur.

GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }

İş arkadaşınız kaydı değiştirir ve sürümü 2 olarak güncelleyen veritabanını günceller:

PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }

Kaydı silmeye çalışıyorsunuz:

DELETE /some-resource/1 { id:1, version:1 }
409 Conflict

İyimser bir kilit istisnası olmalı. Kaydı tekrar okuyun, önemli olduğunu görün ve silinmeyebilir.

Bunu kullanmanın bir başka nedeni, aynı anda birden fazla kaydı silmektir (örneğin, satır seçimi onay kutularına sahip bir ızgara).

DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content

Her iletinin kendi sürümü olduğuna dikkat edin. Belki birden çok başlık kullanarak birden çok sürüm belirtebilirsiniz, ancak George tarafından bu daha basit ve çok daha uygundur.

Bu, Tomcat (7.0.52) ve Spring MVC (4.05) 'de çalışır, muhtemelen daha önceki sürümlerde de bulunur:

@RestController
public class TestController {

    @RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
    SomeBean echoDelete(@RequestBody SomeBean someBean) {
        return someBean;
    }
}

15
GET'te (ve DELETE) gövdelere sahip olmak açıkça HTTP ve REST'e kötü davranıyor. Eşzamanlılık kontrolü ile uğraşmak için başka mekanizmalar da vardır (örneğin If-Modified-Since ve etags).
Bruno

19
Spesifikasyon vücudu DELETE'de yasaklamıyorsa nasıl TEMİZLE kötü muamele yapıyor?
Neil McGuigan

5
Çünkü beden ile bir şey yapmak istemiyorsun. Bakınız: stackoverflow.com/a/983458/372643
Bruno

14
Bu tam olarak aynı konudur: GET, URI tarafından tanımlanan kaynağın temsilini almanızı sağlar ve DELETE, URI tarafından tanımlanan kaynağı siler. Belirli sürümleri silmek istiyorsanız diğer sürümler için farklı bir URI kullanın. URI, HTTP / REST içindeki kaynağın tek tanımlayıcısı olmalıdır. Eğer (örneğin kolu eşzamanlılık yapmak gerekirse başlıklarında için meta verilerden If-Unmodified-Sinceveya EtagNe için olduklarını olduğuna göre).
Bruno

5
Bir gövdedeki sürüm alanı yerine ETag üstbilgisini kullanma
malhal

26

Bana öyle geliyor ki RFC 2616 bunu belirtmiyor.

Bölüm 4.3'ten:

Bir istekte bir ileti gövdesinin varlığı, isteğin ileti başlıklarına bir İçerik Uzunluğu veya Aktarım Kodlaması üstbilgisi alanının eklenmesiyle bildirilir. İstek yönteminin (bölüm 5.1.1) belirtimi, isteklerde varlık gövdesi gönderilmesine izin vermiyorsa, ileti gövdesi bir istekte BULUNMAMALIDIR. Bir sunucu, herhangi bir istek üzerine bir ileti gövdesini okumalı ve iletmelidir; istek yöntemi varlık gövdesi için tanımlı anlambilim içermiyorsa, istek işlenirken ileti gövdesi göz ardı EDİLMELİDİR.

Ve bölüm 9.7:

DELETE yöntemi, kaynak sunucunun Request-URI tarafından tanımlanan kaynağı silmesini ister. Bu yöntem, kaynak sunucuya insan müdahalesi (veya başka yollarla) geçersiz kılınabilir. Kaynak sunucudan döndürülen durum kodu, eylemin başarıyla tamamlandığını gösterse bile, istemcinin işlemin gerçekleştirildiği garanti edilemez. Ancak, yanıt verildiği sırada kaynağı silmeyi veya erişilemeyen bir konuma taşıma niyetinde olmadığı sürece sunucu başarıyı GÖSTERMEMELİDİR.

Yanıt, durumu tanımlayan bir varlık içeriyorsa başarılı bir yanıt 200 (Tamam), eylem henüz yürürlüğe girmediyse 202 (Kabul edildi) veya işlem yürürlüğe girdiyse ancak yanıt içermiyorsa 204 (İçerik Yok) olmalıdır bir varlık.

İstek bir önbellekten geçerse ve İstek URI'sı şu anda önbelleğe alınmış bir veya daha fazla varlığı tanımlarsa, bu girdilere eski olarak davranılmalıdır. Bu yönteme verilen yanıtlar önbelleğe alınamaz. C

Bu nedenle, açıkça izin verilmez veya izin verilmez ve yol boyunca bir proxy'nin ileti gövdesini kaldırma olasılığı vardır (her ne kadar onu okuyup iletmelidir).


19

Sadece bir adım yukarı, DELETE isteğinizde bir gövde sağlar ve bir google bulut HTTPS yük dengeleyici kullanıyorsanız, isteğinizi 400 hatayla reddeder. Kafamı bir duvara çarpıyordum ve Google'ın, hangi nedenle olursa olsun, bir bedenle SİL talebinin hatalı biçimlendirilmiş bir talep olduğunu düşündüğünü öğrendim.


1
for whatever reason- çünkü spec böyle diyor: P
Mardoxx

20
Spesifikasyon "öyle demez" sadece vücudun özel olarak tanımlanmadığını söyler. Eğer tanımlanmamışsa ve bunu göz ardı etmek istiyorsanız, sakin ol ... devam et ve görmezden gel. Ancak, talebi açıkça reddetmek aşırı ve gereksiz görünüyor.
Ben Fried

1
Tanımsız davranışlara güvenmeyin. Oldukça yaygın bir en iyi uygulamadır.
Evert

@ Açıkça tanımsız davranışlar var (örneğin C dilinin özelliklerinde açıkladığınız gibi) ve izin verilen ancak basitçe açıklanmayan davranışlar var. DELETEİkincisi bir ileti gövdesi kullanmaktır .
Alnitak

9

Sürüm 3.0 için OpenAPI belirtiminin, gövdeli DELETE yöntemleri için desteği bıraktığını belirtmek gerekir:

referanslar için buraya ve buraya bakınız

Bu, ileride bu API'lerin uygulanmasını, dokümantasyonunu veya kullanımını etkileyebilir.


7

Görünen o ki, Elastik Arama bunu kullanıyor: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api

Yani Netty bunu destekliyor.

Yorumlarda belirtildiği gibi, artık durum böyle olmayabilir


1
Apache http istemcisi kullanıyorsanız, HttpEntityEnclosingRequestBase öğesini genişleterek ve getMethod () yönteminin GET veya DELETE döndürmesini sağlayarak kendi GET ve DELETE sürümlerinizi kolayca oluşturabilirsiniz. Bunu elasticsearch ile konuşmak için kullanıyoruz.
Jilles van Gurp

2
ölü bağlantı - harika. Biz daha fazla olanlar bağlantı cevapların gerek - değil
cottton

3
Bağlı belgeler artık yalnızca POST istekleri içeriyor, DELETE yok. Bu cevaba bir not eklemeye değer olabilir mi?
dshepherd

Elasticsearch, gövdeyi GET istekleriyle de kullanır.
Nidhin David

7

HTTP posta listesindeki Roy Fielding, http posta listesinde https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html adresini açıklıyor ve şöyle diyor:

GET / DELETE kuruluşunun, talebin işlenmesi veya yorumlanması üzerinde herhangi bir etkisi olması kesinlikle yasaktır.

Bu, gövdenin sunucunun davranışını değiştirmemesi gerektiği anlamına gelir. Sonra ekler:

mesaj çerçevesini korumak için alınan baytları okuma ve atma zorunluluğunun yanı sıra.

Ve son olarak bedeni yasaklamamanın nedeni:

Bir ceset göndermeyi yasaklamamamızın tek nedeni, bunun hiçbir ceset gönderilmeyeceğini varsayarak tembel uygulamalara yol açmasıdır.

İstemciler yük gövdesini gönderebilirken, sunucular bunu bırakmalı ve API'ler bu isteklerde yük gövdesi için bir anlam tanımlamamalıdır.



5

Bir Kuruluşla DELETE kullanmak risklidir ... REST üzerinden Liste İşlemleri için bu yaklaşımı tercih ederim:

Düzenli Operasyonlar

GET / nesneler / Tüm Nesneleri Alır

GET / object / ID Belirtilen kimliğe sahip bir Nesne alır

POST / nesneler Yeni bir Nesne ekler

PUT / object / ID Belirtilen kimliğe sahip bir nesne ekler, bir nesneyi günceller

DELETE / object / ID Belirtilen kimliğe sahip nesneyi siler

Tüm Özel işlemler POST

POST / objects / addList Gövdeye dahil edilen Nesneler Listesi veya Dizisi ekler

POST / objects / deleteList Gövdede bulunan Nesneler Listesini siler

POST / objects / customQuery Gövdedeki özel sorguyu temel alan bir Liste oluşturur

Bir müşteri genişletilmiş işlemlerinizi desteklemiyorsa, düzenli olarak çalışabilir.


A kullanmak POSTyeni kaynaklar oluşturmak için iyi bir RESTy yolu değildir çünkü POST yanıtlarının semantiği özellikle Konum başlıkları bağlamında belirsizdir. Aslında HTTP'yi geride bırakıyorsunuz ve RPC'yi üst üste topluyorsunuz. Uygun "HTTP / REST yolu", başlığı PUTw / kullanarak If-None-Match: *(veya uygun HTTP yöntemlerini belirterek, MKCOLvb.) Kullanarak kaynak oluşturmaktır .
hnh

4

Mevcut cevaplar hakkında çok sayıda harika yorum olmasına rağmen, bunun için iyi bir cevap gönderildiğini düşünmüyorum. Bu yorumların özünü yeni bir cevaba kaldıracağım:

RFC7231'den bu paragraf birkaç kez alıntılanmıştır, bu da özetlemektedir.

DELETE istek iletisindeki bir yükün tanımlanmış bir anlamı yoktur; bir DELETE isteği üzerine bir yük gövdesi göndermek, mevcut bazı uygulamaların isteği reddetmesine neden olabilir.

Diğer cevaplardan kaçırdığım şey ima idi. Evet, DELETEisteklere bir gövde eklemesine izin verilir , ancak anlamsal olarak anlamsızdır. Bunun gerçekten anlamı, DELETEbir istek gövdesi ile bir istek yayınlamanın anlamsal olarak bir istek gövdesi içermemesine eşdeğer olmasıdır.

Bir istek gövdesinin dahil edilmesinin, istek üzerinde herhangi bir etkisi olmamalıdır, bu nedenle hiçbir zaman dahil edilmesinin bir anlamı yoktur.

tl; dr: Teknik DELETEolarak bir istek gövdesine sahip bir talebe izin verilir, ancak bunu yapmak asla yararlı olmaz.


2
"anlamsal olarak anlamsız", "tanımlanmış anlambilimi yoktur" ile aynı anlama gelmez. Birincisi bunun bir anlamı olamaz demektir. İkincisi, RFC'nin kendisinin bu anlambilimin ne olabileceğini belirtmediği anlamına gelir. (RFC yazıyorum)
Alnitak

1
Başka bir deyişle, bir API uygulayıcısı kendileri için bazı anlambilim tanımlamak istiyorsa, bunu yapmak tamamen ücretsizdir.
Alnitak

1
@Alnitak bu kesinlikle yanlış bir yorum. Bu tanıma göre, herhangi bir HTTP istek gövdesinde tanımlı bir anlam bilgisi yoktur, ancak DELETE ve GET spesifikasyonda özellikle çağrılır. İşte henüz GET talebi hakkında konuşulan henüz yayınlanmamış bir taslaktan bir pasaj:
Evert

1
Şu anda piyasaya sürülen RFC'lerde bunun belirsiz olduğu konusunda size katılmıyorum, ancak bana inanmıyorsanız, sizi DELETE ve GET için niyetlerinden sonra yazarlara sormaya davet ediyorum. Cevabımla aynı hizaya geldiğini göreceksiniz. Senin gibi ben de standart kurumlarıyla ilgileniyorum ve sadece RFC'nin nasıl yorumlanması gerektiği konusunda fikir sahibi olan yalnız bir insan değilim.
Evert

2
Eğer durum buysa, o zaman 7231 zayıf bir şekilde ifade edilir ve "yük gövdesi göz ardı EDİLMELİDİR" demelidir. Yukarıda hangi taslağa atıfta bulunuyorsunuz?
Alnitak

3

Herhangi birinin bu sorun testine girmesi durumunda, Hayır evrensel olarak desteklenmez.

Şu anda Sahi Pro ile test ediyorum ve çok açık bir http DELETE çağrı sağlanan herhangi bir vücut veri şeritler (id noktaların uç nokta tasarımına göre toplu olarak silmek için büyük bir liste) şeritler.

Onlarla birkaç kez iletişim kurdum ve incelemeleri için üç ayrı komut dosyası, resim, günlük paketi gönderdim ve hala bunu onaylamadılar. Başarısız bir yama ve cevapsız bir konferans daha sonra desteklerini arayarak hala sağlam bir cevap alamadım.

Sahi'nin bunu desteklemediğinden eminim ve diğer birçok aracın paketi takip ettiğini düşünürdüm.


Sahi Pro'nun en son sürümünde uygulanmaktadır. Sahi HTTP aramaları yapmak için java kullandığından ve Java'nın 1.8 sürümünden önce bir kullanıcının DELETE isteği yapmasına izin vermeyen bir hatası vardı. Böylece Java 1.8 ve sonrasındaki Sahi Pro 6.1.1 (yakında halka açık olacak) ile insanlar Sahi'deki bedenle SİL isteği yapabilirler.
Vivek V Dwivedi

-1

Aşağıdaki cevap olabilir GitHUb url size yardımcı olacaktır. Aslında, Tomcat, Weblogic gibi Uygulama Sunucusu HTTP.DELETE çağrısını istek yükü ile reddediyor. Tüm bunları akılda tutarak, github'a örnek ekledim, lütfen şuna bir göz atın

https://github.com/ashish720/spring-examples


-1

Bir İstek gövdesi ile DELETE işlemini uygulayabildim. AWS Lambda ve AWS API ağ geçidini kullandım ve Go dilini kullandım.


3
Yeteneklerden değil standartlardan bahsediyorlar. Hatta iyi olmayan gövdeli bir GET isteğiniz bile olabilir
ReZa
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.