简体   繁体   English

HTTP DELETE 请求是否允许实体主体?

[英]Is an entity body allowed for an HTTP DELETE request?

When issuing an HTTP DELETE request, the request URI should completely identify the resource to delete.发出 HTTP DELETE 请求时,请求 URI 应完全标识要删除的资源。 However, is it allowable to add extra meta-data as part of the entity body of the request?但是,是否允许在请求的实体主体中添加额外的元数据?

The spec does not explicitly forbid or discourage it, so I would tend to say it is allowed.该规范没有明确禁止或阻止它,所以我倾向于说它是允许的。

Microsoft sees it the same way (I can hear murmuring in the audience), they state in the MSDN article about the DELETE Method of ADO.NET Data Services Framework :微软也有同样的看法(我能听到观众的低语),他们在 MSDN 文章中关于ADO.NET 数据服务框架的 DELETE 方法的文章中指出:

If a DELETE request includes an entity body, the body is ignored [...]如果 DELETE 请求包含实体主体,则该主体将被忽略 [...]

Additionally here is what RFC2616 (HTTP 1.1) has to say in regard to requests:此外,这里是RFC2616 (HTTP 1.1) 关于请求的内容:

  • an entity-body is only present when a message-body is present (section 7.2)实体主体仅在存在消息主体时才存在(第 7.2 节)
  • the presence of a message-body is signaled by the inclusion of a Content-Length or Transfer-Encoding header (section 4.3)包含Content-LengthTransfer-Encoding标头(第 4.3 节)表明消息体的存在
  • a message-body must not be included when the specification of the request method does not allow sending an entity-body (section 4.3)当请求方法的规范不允许发送实体主体时,不得包含消息主体(第 4.3 节)
  • an entity-body is explicitly forbidden in TRACE requests only, all other request types are unrestricted (section 9, and 9.8 specifically)仅在 TRACE 请求中明确禁止实体主体,所有其他请求类型均不受限制(特别是第 9 节和第 9.8 节)

For responses, this has been defined:对于响应,已定义:

  • whether a message-body is included depends on both request method and response status (section 4.3)是否包含消息体取决于请求方法响应状态(第 4.3 节)
  • a message-body is explicitly forbidden in responses to HEAD requests (section 9, and 9.4 specifically)在响应 HEAD 请求时明确禁止消息体(特别是第 9 节和第 9.4 节)
  • a message-body is explicitly forbidden in 1xx (informational), 204 (no content), and 304 (not modified) responses (section 4.3)在 1xx(信息性)、204(无内容)和 304(未修改)响应中明确禁止消息体(第 4.3 节)
  • all other responses include a message-body, though it may be of zero length (section 4.3)所有其他响应都包括一个消息体,尽管它的长度可能为零(第 4.3 节)

The 2014 update to the HTTP 1.1 specification ( RFC 7231 ) explicitly permits an entity-body in a DELETE request: HTTP 1.1 规范 ( RFC 7231 ) 的 2014 更新明确允许在 DELETE 请求中使用实体主体:

A payload within a DELETE request message has no defined semantics; DELETE 请求消息中的有效负载没有定义的语义; sending a payload body on a DELETE request might cause some existing implementations to reject the request.在 DELETE 请求上发送有效负载正文可能会导致某些现有实现拒绝该请求。

Some versions of Tomcat and Jetty seem to ignore a entity body if it is present.某些版本的 Tomcat 和 Jetty 似乎会忽略存在的实体主体。 Which can be a nuisance if you intended to receive it.如果您打算接收它,这可能会很麻烦。

One reason to use the body in a delete request is for optimistic concurrency control.在删除请求中使用正文的一个原因是为了乐观并发控制。

You read version 1 of a record.您阅读了记录的第 1 版。

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

Your colleague reads version 1 of the record.您的同事阅读了记录的第 1 版。

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

Your colleague changes the record and updates the database, which updates the version to 2:您的同事更改了记录并更新了数据库,从而将版本更新为 2:

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

You try to delete the record:您尝试删除记录:

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

You should get an optimistic lock exception.你应该得到一个乐观锁异常。 Re-read the record, see that it's important, and maybe not delete it.重新阅读记录,看看它是否重要,也许不要删除它。

Another reason to use it is to delete multiple records at a time (for example, a grid with row-selection check-boxes).使用它的另一个原因是一次删除多条记录(例如,带有行选择复选框的网格)。

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

Notice that each message has its own version.请注意,每条消息都有自己的版本。 Maybe you can specify multiple versions using multiple headers, but by George, this is simpler and much more convenient.也许您可以使用多个标头指定多个版本,但 George 认为这更简单、更方便。

This works in Tomcat (7.0.52) and Spring MVC (4.05), possibly w earlier versions too:这适用于 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;
    }
}

Just a heads up, if you supply a body in your DELETE request and are using a google cloud HTTPS load balancer, it will reject your request with a 400 error.请注意,如果您在 DELETE 请求中提供正文并使用谷歌云 HTTPS 负载均衡器,它将拒绝您的请求并显示 400 错误。 I was banging my head against a wall and came to found out that Google, for whatever reason, thinks a DELETE request with a body is a malformed request.我正用头撞墙,结果发现无论出于何种原因,Google 都认为带有正文的 DELETE 请求是格式错误的请求。

Roy Fielding on the HTTP mailing list clarifies that on the http mailing list https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html and says: HTTP 邮件列表上的 Roy Fielding 澄清了 http 邮件列表https://lists.w3.org/Archives/Public/ietf-http-wg/2020JanMar/0123.html并说:

GET/DELETE body are absolutely forbidden to have any impact whatsoever on the processing or interpretation of the request GET/DELETE 正文绝对禁止对请求的处理或解释产生任何影响

This means that the body must not modify the behavior of the server.这意味着主体不能修改服务器的行为。 Then he adds:然后他补充说:

aside from the necessity to read and discard the bytes received in order to maintain the message framing.除了必须读取和丢弃接收到的字节以维护消息帧之外。

And finally the reason for not forbidding the body:最后是不禁身的原因:

The only reason we didn't forbid sending a body is because that would lead to lazy implementations assuming no body would be sent.我们没有禁止发送正文的唯一原因是因为这会导致延迟实现,假设不会发送正文。

So while clients can send the payload body, servers should drop it and APIs should not define a semantic for the payload body on those requests.因此,虽然客户端可以发送有效负载正文,但服务器应该删除它,并且 API 不应该为这些请求中的有效负载正文定义语义。

It appears to me that RFC 2616 does not specify this.在我看来, RFC 2616没有指定这一点。

From section 4.3:从第 4.3 节开始:

The presence of a message-body in a request is signaled by the inclusion of a Content-Length or Transfer-Encoding header field in the request's message-headers.请求中消息体的存在通过在请求的消息头中包含 Content-Length 或 Transfer-Encoding 头字段来表示。 A message-body MUST NOT be included in a request if the specification of the request method (section 5.1.1) does not allow sending an entity-body in requests.如果请求方法的规范(第 5.1.1 节)不允许在请求中发送实体主体,则消息主体不得包含在请求中。 A server SHOULD read and forward a message-body on any request;服务器应该在任何请求上读取并转发消息体; if the request method does not include defined semantics for an entity-body, then the message-body SHOULD be ignored when handling the request.如果请求方法不包括为实体主体定义的语义,则在处理请求时应该忽略消息主体。

And section 9.7:第 9.7 节:

The DELETE method requests that the origin server delete the resource identified by the Request-URI. DELETE 方法请求源服务器删除由 Request-URI 标识的资源。 This method MAY be overridden by human intervention (or other means) on the origin server.此方法可能会被源服务器上的人工干预(或其他方式)覆盖。 The client cannot be guaranteed that the operation has been carried out, even if the status code returned from the origin server indicates that the action has been completed successfully.即使从源服务器返回的状态码表明操作已经成功完成,客户端也不能保证操作已经执行。 However, the server SHOULD NOT indicate success unless, at the time the response is given, it intends to delete the resource or move it to an inaccessible location.但是,服务器不应指示成功,除非在给出响应时它打算删除资源或将其移动到无法访问的位置。

A successful response SHOULD be 200 (OK) if the response includes an entity describing the status, 202 (Accepted) if the action has not yet been enacted, or 204 (No Content) if the action has been enacted but the response does not include an entity.如果响应包含描述状态的实体,则成功的响应应该是 200(OK),如果操作尚未制定,则为 202(已接受),或者如果操作已经制定但响应不包括,则应为 204(无内容)一个实体。

If the request passes through a cache and the Request-URI identifies one or more currently cached entities, those entries SHOULD be treated as stale.如果请求通过缓存并且 Request-URI 标识了一个或多个当前缓存的实体,那么这些条目应该被视为陈旧的。 Responses to this method are not cacheable.c对此方法的响应不可缓存。c

So it's not explicitly allowed or disallowed, and there's a chance that a proxy along the way might remove the message body (although it SHOULD read and forward it).所以它没有被明确地允许或禁止,并且沿途的代理有可能会删除消息体(尽管它应该读取并转发它)。

It is worth noting that the OpenAPI specification for version 3.0 dropped support for DELETE methods with a body:值得注意的是,3.0 版的 OpenAPI 规范放弃了对带有主体的 DELETE 方法的支持:

see here and here for references请参阅此处此处以获取参考

This may affect your implementation, documentation, or use of these APIs in the future.这可能会影响您将来对这些 API 的实施、文档或使用。

I don't think a good answer to this has been posted, although there's been lots of great comments on existing answers.我不认为已经发布了一个好的答案,尽管对现有答案有很多很好的评论。 I'll lift the gist of those comments into a new answer:我将把这些评论的要点提升为一个新的答案:

This paragraph from RFC7231 has been quoted a few times, which does sum it up. RFC7231 中的这一段已经被引用了几次,它确实总结了它。

A payload within a DELETE request message has no defined semantics; DELETE 请求消息中的有效负载没有定义的语义; sending a payload body on a DELETE request might cause some existing implementations to reject the request.在 DELETE 请求上发送有效负载正文可能会导致某些现有实现拒绝该请求。

What I missed from the other answers was the implication.我从其他答案中错过的是暗示。 Yes it is allowed to include a body on DELETE requests, but it's semantically meaningless.是的,允许在DELETE请求中包含正文,但它在语义上没有意义。 What this really means is that issuing a DELETE request with a request body is semantically equivalent to not including a request body.这真正意味着发出带有请求正文的DELETE请求在语义上等同于不包括请求正文。

Including a request body should not have any effect on the request, so there is never a point in including it.包含请求正文不应该对请求产生任何影响,因此包含它从来没有意义。

tl;dr: Techically a DELETE request with a request body is allowed, but it's never useful to do so. tl; dr:从技术上讲,允许带有请求正文的DELETE请求,但这样做从来没有用处。

Using DELETE with a Body is risky... I prefer this approach for List Operations over REST:将 DELETE 与 Body 一起使用是有风险的......我更喜欢这种方法用于列表操作而不是 REST:

Regular Operations常规操作

GET /objects/ Gets all Objects GET /objects/获取所有对象

GET /object/ ID Gets an Object with specified ID GET /object/ ID获取具有指定 ID 的 Object

POST /objects Adds a new Object POST /objects添加一个新对象

PUT /object/ ID Adds an Object with specified ID, Updates an Object PUT /object/ ID添加一个具有指定 ID 的对象,更新一个对象

DELETE /object/ ID Deletes the object with specified ID DELETE /object/ ID删除指定 ID 的对象

All Custom actions are POST所有自定义操作都是 POST

POST /objects/ addList Adds a List or Array of Objects included in body POST /objects/ addList添加包含在正文中的对象列表或数组

POST /objects/ deleteList Deletes a List of Objects included in body POST /objects/ deleteList删除包含在正文中的对象列表

POST /objects/ customQuery Creates a List based on custom query in body POST /objects/ customQuery根据正文中的自定义查询创建一个列表

If a client doesn't support your extended operations they can work in the regular way.如果客户不支持您的扩展操作,他们可以以常规方式工作。

It seems ElasticSearch uses this: https://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api似乎 ElasticSearch 使用了这个: https ://www.elastic.co/guide/en/elasticsearch/reference/5.x/search-request-scroll.html#_clear_scroll_api

Which means Netty support this.这意味着 Netty 支持这一点。

Like mentionned in comments it may not be the case anymore就像评论中提到的那样,情况可能不再如此

In case anyone is running into this issue testing, No, it is not universally supported.如果有人遇到这个问题测试,不,它不是普遍支持的。

I am currently testing with Sahi Pro and it is very apparent a http DELETE call strips any provided body data (a large list of IDs to delete in bulk, as per endpoint design).我目前正在使用 Sahi Pro 进行测试,很明显,http DELETE 调用会剥离任何提供的正文数据(根据端点设计,要批量删除的大量 ID 列表)。

I have been in contact with them several times, also sent three separate packages of scripts, images and logs for them to review and they still have not confirmed this.我已经和他们联系过几次,还发送了三个单独的脚本、图像和日志包供他们审查,但他们仍然没有确认这一点。 A failed patch, and a missed conference calls by their support later and I still haven't gotten a solid answer.一个失败的补丁,后来他们的支持错过了电话会议,我仍然没有得到一个可靠的答案。

I am certain Sahi does not support this, and I would imagine many other tools follow suite.我确信 Sahi 不支持这一点,我想还有很多其他工具会效仿。

This is not defined .这没有定义

A payload within a DELETE request message has no defined semantics; DELETE 请求消息中的有效负载没有定义的语义; sending a payload body on a DELETE request might cause some existing implementations to reject the request.在 DELETE 请求上发送有效负载正文可能会导致某些现有实现拒绝该请求。
https://www.rfc-editor.org/rfc/rfc7231#page-29 https://www.rfc-editor.org/rfc/rfc7231#page-29

Practical answer: NO实际答案:否

Some clients and servers ignore or even delete the body in DELETE request.一些客户端和服务器会忽略甚至删除 DELETE 请求中的正文。 In some rare cases they fail and return an error.在极少数情况下,它们会失败并返回错误。

Several other answers mention RFC 7231 which had effectively said that a DELETE request is allowed to have a body but it is not recommended.其他几个答案提到了 RFC 7231,它有效地表示允许DELETE请求具有正文,但不建议这样做。

In 2022, RFC 7231 was superseded by RFC 9110: HTTP Semantics , which now says: 2022 年,RFC 7231 被RFC 9110: HTTP Semantics取代,现在说:

[...] 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 [...]. [...] DELETE 请求中收到的内容没有一般定义的语义,不能改变请求的含义或目标,并且可能导致某些实现拒绝请求并关闭连接 [...]。 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.客户端不应该在 DELETE 请求中生成内容,除非它是直接向源服务器发出的,该源服务器先前已在带内或带外指示此类请求有目的并且将得到充分支持。 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.源服务器不应该依赖私有协议来接收内容,因为 HTTP 通信的参与者通常不知道请求链中的中介。

This language has been strengthened from the previous language, to say that even though it is allowed, you really need to be very careful when using it because (for example) some users might be behind a proxy that would strip the body from the request in order to combat "request smuggling" .这种语言已经从以前的语言中得到了加强,也就是说,即使它被允许,你在使用它时确实需要非常小心,因为(例如)某些用户可能在代理后面,该代理会从请求中删除正文为了打击“请求走私”

It's better to do not use body within DELETE.最好不要在 DELETE 中使用 body。 It's not supported by many tools, Swagger is an example.许多工具都不支持它,Swagger 就是一个例子。

Might be the below GitHUb url will help you, to get the answer.可能是下面的 GitHub 网址会帮助你,得到答案。 Actually, Application Server like Tomcat, Weblogic denying the HTTP.DELETE call with request payload.实际上,像 Tomcat 这样的应用程序服务器,Weblogic 拒绝了带有请求负载的 HTTP.DELETE 调用。 So keeping these all things in mind, I have added example in github,please have a look into that所以请记住这些,我在 github 中添加了示例,请查看

https://github.com/ashish720/spring-examples https://github.com/ashish720/spring-examples

I was able to implement DELETE operation with a Request body.我能够使用请求主体实现 DELETE 操作。 I used AWS Lambda and AWS API gateway and used Go language.我使用了 AWS Lambda 和 AWS API 网关并使用了 Go 语言。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM