发出HTTP DELETE请求时,请求URI应完全标识要删除的资源。但是,是否允许添加额外的元数据作为请求的实体主体的一部分?
答案 0 :(得分:490)
The spec没有明确禁止或劝阻它,所以我倾向于说它是允许的。
微软以同样的方式看待它(我可以听到观众中的嘀咕声),他们在MSDN文章中指出DELETE Method of ADO.NET Data Services Framework:
如果DELETE请求包含实体主体,则会忽略正文[...]
此外,RFC2616(HTTP 1.1)对请求的说法如下:
Content-Length
或Transfer-Encoding
标题(第4.3节)来表示存在消息正文 对于回复,已定义:
答案 1 :(得分:144)
HTTP 1.1规范的最新更新(RFC 7231)明确允许DELETE请求中的实体主体:
DELETE请求消息中的有效负载没有定义的语义;在DELETE请求上发送有效负载主体可能会导致某些现有实现拒绝该请求。
答案 2 :(得分:52)
某些版本的Tomcat和Jetty似乎忽略了实体主体(如果存在)。如果您打算收到它,这可能会令人讨厌。
答案 3 :(得分:44)
在删除请求中使用正文的一个原因是乐观并发控制。
您阅读的是记录的第1版。
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
您的同事阅读记录的第1版。
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
您的同事更改记录并更新数据库,将版本更新为2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
您尝试删除记录:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
您应该获得乐观的锁定异常。重新阅读记录,看它很重要,也许不能删除它。
使用它的另一个原因是一次删除多个记录(例如,带有行选择复选框的网格)。
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
请注意,每条消息都有自己的版本。也许你可以使用多个标题来指定多个版本,但是通过George,这更简单,更方便。
这适用于Tomcat(7.0.52)和Spring MVC(4.05),也可能是早期版本:
@RestController
public class TestController {
@RequestMapping(value="/echo-delete", method = RequestMethod.DELETE)
SomeBean echoDelete(@RequestBody SomeBean someBean) {
return someBean;
}
}
答案 4 :(得分:27)
在我看来,RFC 2616没有指明这一点。
从第4.3节开始:
请求中存在消息正文 包含Content-Length或Transfer-Encoding标头字段 请求的消息头。邮件正文不得包含在内 如果请求方法的规范请求(第5.1.1节) 不允许在请求中发送实体主体。服务器应该 在任何请求上读取和转发消息正文;如果是请求方法 不包含实体主体的定义语义,然后是 处理请求时,应该忽略message-body。
第9.7节:
DELETE方法请求源服务器删除资源 由Request-URI标识。这种方法可以被人类覆盖 原始服务器上的干预(或其他方式)。客户不能 保证操作已经进行,即使是 从原始服务器返回的状态代码表示该操作 已成功完成。但是,服务器不应该 除非在给出答复时表明成功 打算删除资源或将其移动到无法访问的资源 位置。
如果响应包含一个,那么成功的响应应该是200(OK) 描述状态的实体,202(已接受),如果操作没有 尚未颁布,或204(无内容),如果该行动已经颁布 但是回复不包括实体。
如果请求通过缓存并且Request-URI标识 一个或多个当前缓存的实体,这些条目应该是 被视为陈旧。对此方法的响应不是cacheable.c
所以它没有被明确允许或禁止,并且沿途的代理可能会删除消息体(尽管它应该读取并转发它)。
答案 5 :(得分:15)
如果您在DELETE请求中提供正文并且正在使用Google云端HTTPS负载均衡器,那么它将拒绝您的请求,并出现400错误。我正撞在墙上,发现Google无论出于何种原因认为带有正文的DELETE请求是一个格式错误的请求。
答案 6 :(得分:12)
HTTP邮件列表上的Roy Fielding澄清了http邮件列表https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html上的内容,并说:
GET / DELETE身体绝对禁止有任何影响 处理或解释请求
这意味着主体不得修改服务器的行为。 然后他添加:
除了 读取和丢弃接收到的字节以保持其必要性 消息框架。
最后是禁止遗体的原因:
我们不禁止发送尸体的唯一原因是 因为假设没有人会导致懒惰的实现 被发送。
因此,尽管客户端可以发送有效内容主体,但服务器应将其丢弃 并且API不应在这些请求上为有效载荷主体定义语义。
答案 7 :(得分:7)
ElasticSearch似乎使用了这个: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api
这意味着Netty支持这一点。
在评论中提到它可能不再是这种情况
答案 8 :(得分:6)
未定义。
DELETE请求消息中的有效负载没有定义的语义; 在DELETE请求上发送有效负载主体可能会导致某些存在 拒绝请求的实现。
https://tools.ietf.org/html/rfc7231#page-29
答案 9 :(得分:5)
答案 10 :(得分:3)
如果有人遇到此问题测试,请不要普遍支持。
我目前正在使用Sahi Pro进行测试,很明显一个http DELETE调用剥离任何提供的正文数据(根据端点设计批量删除大量的id)。
我已经多次与他们联系,并且发送了三个单独的包裹,图像,日志包供他们审查,他们仍然没有证实这一点。一个失败的补丁,以及之后他们的支持错过了电话会议,我仍然没有得到一个可靠的答案。
我确信Sahi不支持这一点,我会想到许多其他工具都可以使用套件。
答案 11 :(得分:3)
尽管现有答案有很多不错的评论,但我认为对此并没有给出很好的答案。我将这些评论的要点变成一个新的答案:
This paragraph from RFC7231被引用了几次,但确实将其汇总。
DELETE请求消息中的有效负载没有定义的语义; 在DELETE请求上发送有效内容正文可能会导致一些现有内容 拒绝请求的实现。
我从其他答案中错过的是含义。是的,它可以在DELETE
请求中包含正文,但是在语义上是没有意义的。这的真正含义是,发出带有请求正文的DELETE
请求在语义上等同于不包括请求正文。
包括请求正文对请求不会有任何影响,因此将其包含在内根本没有意义。
tl; dr:从技术上讲,允许带有请求正文的DELETE
请求,但这样做绝对没有用。
答案 12 :(得分:1)
我能够通过Request主体实现DELETE操作。我使用了AWS Lambda和AWS API网关,并使用了Go语言。
答案 13 :(得分:0)
与主体一起使用DELETE是有风险的...与REST相比,我更喜欢这种用于列表操作的方法:
常规操作
获取 / objects / 获取所有对象
获取 / object / ID 获取具有指定ID的对象
POST /对象 添加新对象
输入 / object / ID 添加具有指定ID的对象,更新对象
删除 / object / ID 删除具有指定ID的对象
所有自定义操作均为POST
POST / objects / addList 添加正文中包含的对象列表或对象
POST / objects / deleteList 删除正文中包含的对象列表
POST / objects / customQuery 基于正文中的自定义查询创建列表
如果客户不支持您的扩展操作,他们可以按常规方式工作。
答案 14 :(得分:0)
实际答案:否
一些客户端和服务器会忽略甚至删除 DELETE 请求中的正文。在极少数情况下,它们会失败并返回错误。
答案 15 :(得分:-1)
下面的GitHUb网址可能会帮助您获得答案。 实际上,像Tomcat这样的Application Server,Weblogic拒绝带有请求有效负载的HTTP.DELETE调用。因此请牢记所有这些内容,我在github中添加了示例,请仔细阅读