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


当前回答

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

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

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

其他回答

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

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

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

只是一个提示,如果你在你的DELETE请求中提供了一个主体,并且使用了谷歌云HTTPS负载均衡器,它将拒绝你的请求,错误为400。我的头撞到墙上,然后发现谷歌,不管出于什么原因,认为一个带有主体的DELETE请求是一个畸形的请求。

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

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

这个没有定义。

DELETE请求消息中的有效负载没有定义的语义; 在DELETE请求上发送有效负载主体可能会导致一些现有的问题 实现来拒绝请求。 https://www.rfc-editor.org/rfc/rfc7231#page-29

值得注意的是,OpenAPI 3.0版本的规范放弃了对带体的DELETE方法的支持:

请看这里和这里的参考资料

这可能会影响将来这些api的实现、文档或使用。