首页 文章

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

提问于
浏览
553

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

10 回答

  • 51

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

    这意味着Netty支持这一点 .

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

  • 45

    The spec没有明确禁止或劝阻它,所以我倾向于说它是允许的 .

    微软以同样的方式看待它(我可以听到 Spectator 中的嘀咕声),他们在MSDN文章中指出DELETE Method of ADO.NET Data Services Framework

    如果DELETE请求包含实体主体,则忽略正文[...]

    另外这里是RFC2616(HTTP 1.1)关于请求的说法:

    • 实体主体仅在存在消息体时出现(第7.2节)

    • 通过包含 Content-LengthTransfer-Encoding Headers (第4.3节)表示存在消息正文

    • 当请求方法的规范不允许发送实体主体时,不得包含消息体(第4.3节)

    • 仅在TRACE请求中明确禁止实体主体,所有其他请求类型不受限制(具体为第9节和第9.8节)

    对于回复,已定义:

    • 是否包含消息正文取决于请求方法和响应状态(第4.3节)

    • 在对HEAD请求的响应中明确禁止消息体(具体为第9节和第9.4节)

    • 在1xx(信息),204(无内容)和304(未修改)响应中明确禁止消息正文(第4.3节)

    • 所有其他响应都包含一个消息体,尽管它的长度可能为零(第4.3节)

  • 2

    HTTP 1.1规范的最新更新(RFC 7231)明确允许DELETE请求中的实体主体:

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

  • 7

    如果有人遇到此问题测试,请不要普遍支持 .

    我目前正在使用Sahi Pro进行测试,很明显一个http DELETE调用剥离任何提供的正文数据(根据 endpoints 设计批量删除大量的id) .

    我已经多次与他们联系,并且发送了三个单独的包裹,图像,日志包供他们审查,他们仍然没有证实这一点 . 一个失败的补丁,以及之后他们的支持错过了电话 Session ,我仍然没有得到一个可靠的答案 .

    我确信Sahi不支持这个,我会想象许多其他工具都会跟随套件 .

  • 126

    值得注意的是,版本3.0的OpenAPI规范放弃了对具有正文的DELETE方法的支持:

    请参阅herehere以获取参考

    这可能会影响您将来实施,记录或使用这些API .

  • 6

    如果您在DELETE请求中提供正文并且正在使用谷歌 Cloud HTTPS负载均衡器,它将拒绝您的请求400错误 . 我正撞在墙上,发现Google出于某种原因认为带有正文的DELETE请求是一个格式错误的请求 .

  • 14

    在我看来,RFC 2616没有指定这一点 .

    从第4.3节:

    通过在请求的消息头中包含Content-Length或Transfer-Encoding头字段来指示请求中是否存在消息正文 . 如果请求方法的规范(第5.1.1节)不允许在请求中发送实体主体,则消息主体不得包含在请求中 . 服务器应该在任何请求上读取和转发消息体;如果请求方法不包含实体主体的定义语义,那么在处理请求时应该忽略消息主体 .

    第9.7节:

    DELETE方法请求源服务器删除Request-URI标识的资源 . 可以通过源服务器上的人为干预(或其他方式)覆盖此方法 . 即使从源服务器返回的状态代码表明操作已成功完成,也无法保证客户端已执行该操作 . 但是,服务器不应该指示成功,除非在给出响应时,它打算删除资源或将其移动到不可访问的位置 . 如果响应包括描述状态的实体,则成功响应应为200(OK),如果操作尚未执行,则应为202(已接受);如果操作已颁布但响应不包括,则应为204(无内容)一个实体 . 如果请求通过缓存并且Request-URI标识一个或多个当前缓存的实体,那么这些条目应该被视为陈旧 . 对此方法的响应不是cacheable.c

    所以它没有被明确允许或禁止,并且沿途的代理可能会删除消息体(尽管它应该读取并转发它) .

  • 3

    This is not defined .

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

  • 451

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

    您阅读了记录的第1版 .

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

    您的同事阅读记录的第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;
        }
    }
    
  • 27

    某些版本的Tomcat和Jetty似乎忽略了实体主体(如果存在) . 如果您打算收到它可能会令人讨厌 .

相关问题