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


当前回答

对Body使用DELETE是有风险的…比起REST,我更喜欢这种列表操作方法:

常规操作

GET /objects/获取所有对象

GET /object/ID获取指定ID的对象

POST /objects添加一个新对象

PUT /object/ID添加指定ID的对象,更新对象

DELETE /object/ID删除指定ID的对象

所有自定义操作都是POST

POST /objects/addList添加body中包含的对象列表或数组

POST /objects/deleteList删除包含在body中的对象列表

POST /objects/customQuery基于body中的自定义查询创建一个List

如果客户不支持您的扩展操作,他们可以以常规方式工作。

其他回答

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

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

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

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

最后是不禁止尸体的原因

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

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

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

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

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;
    }
}

如果有人在测试中遇到这个问题,不,它不是普遍支持的。

我目前正在用Sahi Pro进行测试,很明显,http DELETE调用剥离了任何提供的主体数据(根据端点设计批量删除的大量id列表)。

我已经和他们联系了几次,也把脚本、图片、日志三个包分开发给他们审核,他们还没有确认。一个失败的补丁,后来他们的支持缺席了电话会议,我仍然没有得到一个可靠的答案。

我确定Sahi不支持这个功能,而且我可以想象有许多其他的工具跟随套件。

规范并没有明确禁止或阻止它,所以我倾向于说它是允许的。

微软也是这么看的(我能听到听众的嘀嘀声),他们在MSDN的文章中提到了ADO的DELETE方法。NET数据服务框架:

如果一个DELETE请求包含一个实体体,该实体体将被忽略[…]

此外,这里是RFC2616 (HTTP 1.1)在请求方面所说的:

只有当消息体出现时,entity-body才会出现(第7.2节) 消息体的存在通过包含内容长度或传输编码头来表示(第4.3节)。 当请求方法的规范不允许发送实体体时(第4.3节),就不能包含消息体。 仅在TRACE请求中明确禁止使用实体体,所有其他类型的请求都不受限制(第9节,特别是9.8节)

对于响应,这已被定义为:

是否包含消息体取决于请求方法和响应状态(第4.3节) 明确禁止在HEAD请求的响应中使用消息体(第9节和9.4节) 1xx(信息)、204(无内容)和304(未修改)响应中明确禁止消息体(第4.3节) 所有其他响应都包含消息体,尽管消息体可能为零长度(第4.3节)

更新

在RFC 9110(2022年6月)中,明确了GET、HEAD和DELETE上的请求体不可互操作的事实。

9.3.5删除

Although request message framing is independent of the method used, 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 because of its potential as a request smuggling attack (Section 11.2 of [HTTP/1.1]). 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请求消息中的有效负载没有定义的语义; 在DELETE请求上发送有效负载主体可能会导致一些现有的问题 实现来拒绝请求。 https://www.rfc-editor.org/rfc/rfc7231#page-29