在发出HTTP DELETE请求时,请求URI应该完全标识要删除的资源。但是,是否允许添加额外的元数据作为请求实体主体的一部分?


当前回答

其他几个回答提到了RFC 7231,它有效地说了DELETE请求可以有一个主体,但不推荐。

在2022年,RFC 7231被RFC 9110: HTTP语义所取代,它现在说:

[...] content received in a DELETE request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection [...]. A client SHOULD NOT generate content in a DELETE request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

这种语言在之前的语言基础上得到了加强,也就是说,即使它是允许的,在使用它时也需要非常小心,因为(例如)一些用户可能在代理的背后,为了打击“请求走私”而从请求中剥离主体。

其他回答

实际答案:不

有些客户端和服务器会忽略甚至删除delete请求中的主体。在极少数情况下,它们会失败并返回错误。

在删除请求中使用主体的一个原因是为了进行乐观并发控制。

你读了唱片的第一个版本。

GET /some-resource/1
200 OK { id:1, status:"unimportant", version: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;
    }
}

2014年更新的HTTP 1.1规范(RFC 7231)明确地允许在DELETE请求中使用实体:

DELETE请求消息中的有效负载没有定义的语义;在DELETE请求上发送有效负载主体可能会导致某些现有实现拒绝该请求。

Roy Fielding在HTTP邮件列表上澄清了HTTP邮件列表https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html并说:

GET/DELETE主体绝对禁止产生任何影响 对请求的处理或解释

这意味着主体不能修改服务器的行为。 然后他补充道:

除了 为了维护,必须读取和丢弃接收到的字节 信息框架。

最后是不禁止尸体的原因

我们不禁止派人去的唯一原因是 因为这将导致懒惰的实现,假设没有人会这样做 被发送。

因此,当客户端可以发送有效负载主体时,服务器应该丢弃它 和api不应该为这些请求的有效载荷体定义语义。

其他几个回答提到了RFC 7231,它有效地说了DELETE请求可以有一个主体,但不推荐。

在2022年,RFC 7231被RFC 9110: HTTP语义所取代,它现在说:

[...] content received in a DELETE request has no generally defined semantics, cannot alter the meaning or target of the request, and might lead some implementations to reject the request and close the connection [...]. A client SHOULD NOT generate content in a DELETE request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

这种语言在之前的语言基础上得到了加强,也就是说,即使它是允许的,在使用它时也需要非常小心,因为(例如)一些用户可能在代理的背后,为了打击“请求走私”而从请求中剥离主体。