允许HTTP DELETE请求的实体主体?

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

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

微软认为它也是一样(我可以听到在听众中嘀咕),他们在MSDN关于ADO.NET数据服务框架的DELETE方法的文章中说:

如果DELETE请求包含实体主体,则忽略主体

另外这里是什么RFC2616 (HTTP 1.1)在请求方面说:

  • 当一个消息体出现时,一个实体主体才会出现(7.2节)
  • 消息体的存在通过包含一个Content-Length或者Transfer-Encoding头来表示(4.3节)
  • 当请求方法的规范不允许发送实体主体时, 消息体不能包含在内(4.3节)
  • TRACE请求中明确禁止实体主体 ,所有其他请求types不受限制(第9节和第9.8节)

对于答复,这已被定义为:

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

对HTTP 1.1规范( RFC 7231 )的最新更新显式允许实体主体在DELETE请求中:

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

Tomcat和Jetty的某些版本似乎忽略实体主体(如果存在)。 如果你打算收到这个,这可能是一个麻烦。

在删除请求中使用正文的一个原因是乐观的并发控制。

您阅读logging的第1版。

 GET /some-resource/1 200 OK { id:1, status:"unimportant", version:1 } 

你的同事阅读logging的第一个版本。

 GET /some-resource/1 200 OK { id:1, status:"unimportant", version:1 } 

您的同事更改logging并更新数据库,该数据库将版本更新为2:

 PUT /some-resource/1 { id:1, status:"important", version:1 } 200 OK { id:1, status:"important", version:2 } 

您尝试删除该logging:

 DELETE /some-resource/1 { id:1, version:1 } 409 Conflict 

你应该得到一个乐观的lockingexception。 重新阅读logging,看到这是重要的,也许不会删除它。

使用它的另一个原因是一次删除多个logging(例如,具有行selectcheckbox的网格)。

 DELETE /messages [{id:1, version:2}, {id:99, version:3}] 204 No Content 

注意每条消息都有自己的版本。 也许你可以指定多个版本使用多个头,但乔治,这是更简单,更方便。

这可以在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; } } 

在我看来, RFC 2616没有指定这个。

从第4.3节:

请求中消息主体的存在通过在请求的消息头中包含Content-Length或Transfer-Encoding头域来进行标记。 如果请求方法(5.1.1节)的规范不允许在请求中发送实体主体,则消息主体不能包含在请求中。 服务器应该读取并转发任何请求的消息体; 如果请求方法不包含实体主体的定义的语义,那么在处理请求时应该忽略消息主体。

而第9.7节:

DELETE方法请求源服务器删除由Request-URI标识的资源。 这种方法可能会被原始服务器上的人为干预(或其他方式)覆盖。 即使从原始服务器返回的状态码指示操作已成功完成,客户端也不能保证已执行操作。 但是,服务器不应该表示成功,除非在给出响应时,它打算删除资源或将其移动到不可访问的位置。

如果响应包括描述状态的实体,则成功的响应应该是200(OK),如果该操作尚未实施,则成功响应202(接受),如果该操作已经被实施,则响应不包括204(无内容)一个实体。

如果请求通过caching并且Request-URI标识了一个或多个当前caching的实体,那么这些条目应该被视为陈旧。 对此方法的响应不是cacheable.c

所以它没有明确的允许或者不被允许,而且沿途的代理可能会删除消息体(尽pipe它应该读取和转发)。

看来ElasticSearch使用这个: https ://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api

这意味着Netty支持这一点。

就像在评论中提到的那样,情况可能不是这样了

如果您在DELETE请求中提供正文,并且正在使用Google云HTTPS负载平衡器,则会以400错误拒绝您的请求。 我正在撞墙,发现Google不pipe出于何种原因都认为DELETE对身体的请求是一个畸形的请求。

如果有人遇到这个问题testing,不,它不是普遍支持。

我目前正在使用Sahi Pro进行testing,很明显,使用http DELETE调用可以提取任何提供的主体数据(根据端点devise批量删除的大量列表)。

我已经和他们多次联系过,还有三个单独的纸条,图像,日志包供他们审查,他们还没有证实这一点。 一个失败的补丁,以及一个错过的电话会议后来的支持,我仍然没有得到一个坚实的答案。

我确信Sahi不支持这一点,我会想象许多其他工具遵循套件。

这没有定义

DELETE请求消息中的有效载荷没有定义的语义; 在DELETE请求上发送一个负载体可能会导致一些现有的实现拒绝这个请求。
https://tools.ietf.org/html/rfc7231#page-29