发出HTTP DELETE请求时,请求URI应完全标识要删除的资源.但是,是否允许添加额外的元数据作为请求的实体主体的一部分?
Tom*_*lak 527
该规范没有明确禁止或阻止它,所以我倾向于说它是允许的.
微软以同样的方式看待它(我可以听到观众中的嘀咕声),他们在MSDN文章中指出ADO.NET数据服务框架的DELETE方法:
如果DELETE请求包含实体主体,则忽略正文[...]
另外这里是RFC2616(HTTP 1.1)对请求的说法:
Content-LengthTransfer-Encoding对于回复,这已经定义:
grz*_*zes 154
HTTP 1.1规范(RFC 7231)的最新更新明确允许DELETE请求中的实体主体:
DELETE请求消息中的有效负载没有定义的语义; 在DELETE请求上发送有效负载主体可能会导致某些现有实现拒绝该请求.
eva*_*ard 53
某些版本的Tomcat和Jetty似乎忽略了实体主体(如果存在).如果您打算收到它可能会令人讨厌.
Nei*_*gan 45
在删除请求中使用正文的一个原因是乐观并发控制.
您阅读了记录的第1版.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Run Code Online (Sandbox Code Playgroud)
您的同事阅读记录的第1版.
GET /some-resource/1
200 OK { id:1, status:"unimportant", version:1 }
Run Code Online (Sandbox Code Playgroud)
您的同事更改记录并更新数据库,将版本更新为2:
PUT /some-resource/1 { id:1, status:"important", version:1 }
200 OK { id:1, status:"important", version:2 }
Run Code Online (Sandbox Code Playgroud)
您尝试删除记录:
DELETE /some-resource/1 { id:1, version:1 }
409 Conflict
Run Code Online (Sandbox Code Playgroud)
您应该获得乐观的锁定异常.重新阅读记录,看它是重要的,也许不能删除它.
使用它的另一个原因是一次删除多个记录(例如,带有行选择复选框的网格).
DELETE /messages
[{id:1, version:2},
{id:99, version:3}]
204 No Content
Run Code Online (Sandbox Code Playgroud)
请注意,每条消息都有自己的版本.也许你可以使用多个标题来指定多个版本,但是通过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;
}
}
Run Code Online (Sandbox Code Playgroud)
Ada*_*eld 27
在我看来,RFC 2616没有指定这一点.
从第4.3节:
通过在请求的消息头中包含Content-Length或Transfer-Encoding头字段来指示请求中消息体的存在.如果请求方法的规范(第5.1.1节)不允许在请求中发送实体主体,则消息主体不得包含在请求中.服务器应该在任何请求上读取和转发消息体; 如果请求方法不包含实体主体的定义语义,那么在处理请求时应该忽略消息主体.
第9.7节:
DELETE方法请求源服务器删除Request-URI标识的资源.可以通过源服务器上的人为干预(或其他方式)覆盖此方法.即使从源服务器返回的状态代码表明操作已成功完成,也无法保证客户端已执行该操作.但是,服务器不应该指示成功,除非在给出响应时,它打算删除资源或将其移动到不可访问的位置.
如果响应包括描述状态的实体,则成功响应应为200(OK),如果操作尚未执行,则应为202(已接受);如果操作已颁布但响应不包括,则应为204(无内容)一个实体.
如果请求通过缓存并且Request-URI标识了一个或多个当前缓存的实体,那么这些条目应该被视为陈旧.对此方法的响应不是cacheable.c
所以它没有被明确允许或禁止,并且沿途的代理可能会删除消息体(尽管它应该读取并转发它).
Ben*_*ied 17
只是抬头,如果您在DELETE请求中提供正文并使用Google云端HTTPS负载均衡器,它将拒绝您的请求,并出现400错误.我正撞在墙上,发现Google出于某种原因认为带有正文的DELETE请求是一个格式错误的请求.
Rob*_*lli 14
HTTP 邮件列表上的 Roy Fielding 在 http 邮件列表https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html上澄清了这一点, 并说:
GET/DELETE 主体绝对禁止对请求的处理或解释产生任何影响
这意味着主体不得修改服务器的行为。然后他补充道:
除了读取和丢弃接收到的字节以维护消息帧的必要性之外。
最后是不禁止身体的原因:
我们没有禁止发送正文的唯一原因是因为这会导致假设不发送正文的懒惰实现。
因此,虽然客户端可以发送有效负载正文,但服务器应该删除它,并且 API 不应为这些请求的有效负载正文定义语义。
小智 10
将 DELETE 与 Body 一起使用是有风险的......我更喜欢这种列表操作而不是 REST 的方法:
常规操作
GET /objects/ 获取所有对象
GET /object/ ID 获取指定ID的对象
POST /objects 添加一个新对象
PUT /object/ ID 添加具有指定 ID 的对象,更新对象
DELETE /object/ ID 删除指定 ID 的对象
所有自定义操作都是 POST
POST /objects/ addList 添加包含在正文中的对象列表或数组
POST /objects/ deleteList 删除包含在正文中的对象列表
POST /objects/ customQuery 根据正文中的自定义查询创建一个列表
如果客户不支持您的扩展操作,他们可以按常规方式工作。
我不认为已经发布了一个很好的答案,尽管对现有答案有很多很好的评论。我将把这些评论的要点提炼成一个新的答案:
RFC7231中的这一段被引用了几次,总结了一下。
DELETE 请求消息中的有效载荷没有定义的语义;在 DELETE 请求上发送有效负载正文可能会导致某些现有实现拒绝该请求。
我从其他答案中错过的是暗示。是的,允许在DELETE请求中包含主体,但在语义上没有意义。这真正意味着发出DELETE带有请求正文的请求在语义上等同于不包括请求正文。
包含请求正文不应对请求产生任何影响,因此包含它没有任何意义。
tl; dr:从技术上讲DELETE,允许带有请求正文的请求,但这样做永远没有用。
其他 几个答案提到了 RFC 7231,它有效地表示DELETE允许请求有主体,但不建议这样做。
2022 年,RFC 7231 被RFC 9110: HTTP Semantics取代,现在表示:
[...] DELETE 请求中收到的内容没有一般定义的语义,无法更改请求的含义或目标,并且可能导致某些实现拒绝请求并关闭连接 [...]。客户端不应该在 DELETE 请求中生成内容,除非该请求直接发送到先前已在带内或带外表明此类请求具有目的且将得到充分支持的源服务器。源服务器不应该依赖私有协议来接收内容,因为 HTTP 通信的参与者通常不知道请求链上的中介。
这种语言比以前的语言得到了加强,也就是说,即使允许,但在使用它时您确实需要非常小心,因为(例如)某些用户可能位于代理后面,该代理会从请求中剥离正文以打击“请求走私”。
小智 6
这没有定义.
DELETE请求消息中的有效负载没有定义的语义; 在DELETE请求上发送有效负载主体可能会导致某些现有实现拒绝该请求.
https://tools.ietf.org/html/rfc7231#page-29
| 归档时间: |
|
| 查看次数: |
360085 次 |
| 最近记录: |