首页 文章

DELETE Request Body的RESTful替代方案

提问于
浏览
81

虽然HTTP 1.1 spec似乎允许DELETE请求上的消息体,但它似乎表明服务器应该忽略它,因为它没有定义的语义 .

4.3消息体服务器应该在任何请求上读取和转发消息体;如果请求方法不包含实体主体的定义语义,那么在处理请求时应该忽略消息主体 .

我已经回顾了有关SO及其他内容的几个相关讨论,例如:

大多数讨论似乎都同意允许在DELETE上提供消息体,但通常不建议这样做 .

此外,我注意到各种HTTP客户端库中的趋势,这些库中似乎记录了越来越多的增强功能,以支持DELETE上的请求主体 . 大多数图书馆似乎都有责任,尽管偶尔会有一些初步阻力 .

我的用例要求在DELETE上添加一些必需的元数据(例如删除的“原因”,以及删除所需的一些其他元数据) . 我已经考虑了以下选项,其中任何一个看起来都不合适,并且与HTTP规范和/或REST最佳实践内联:

  • Message Body - 规范表明DELETE上的消息体没有语义值; HTTP客户端不完全支持;不是标准做法

  • Custom HTTP Headers - 要求自定义 Headers 通常为against standard practices;使用它们与我的其余API不一致,其中没有一个需要自定义标头;此外,没有好的HTTP响应可用于指示错误的自定义标头值(可能是一个单独的问题)

  • Standard HTTP Headers - 没有标准 Headers 是合适的

  • Query Parameters - 添加查询参数实际上会更改要删除的Request-URI; against standard practices

  • POST Method - (例如 POST /resourceToDelete { deletemetadata } )POST不是删除的语义选项; POST实际上代表了所需的相反操作(即POST创建资源下属;但我需要删除资源)

  • Multiple Methods - 将DELETE请求拆分为两个操作(例如PUT删除元数据,然后删除DELETE)将原子操作拆分为两个,可能会留下不一致的状态 . 删除原因(和其他相关元数据)不是资源表示本身的一部分 .

我的第一个偏好可能是使用消息体,第二个是自定义HTTP头;但是,如上所述,这些方法存在一些缺点 .

是否有任何与REST / HTTP标准一致的建议或最佳实践,以便在DELETE请求中包含此类必需的元数据?还有其他我没有考虑的替代方案吗?

4 回答

  • 7

    尽管有些建议不要将消息体用于DELETE请求,但这种方法可能适用于某些用例 . 这是我们在评估问题/答案中提到的其他选项以及与服务的消费者合作之后最终使用的方法 .

    虽然消息体的使用并不理想,但其他选项都不是完全适合的 . 请求体DELETE允许我们轻松,清晰地添加伴随DELETE操作所需的其他数据/元数据的语义 .

    我仍然对其他想法和讨论持开放态度,但想要关闭这个问题的循环 . 我感谢大家对这个主题的想法和讨论!

  • 0

    你似乎想要的是两件事之一,它们都不是纯粹的 DELETE

    • You have two operations, PUT 删除原因后跟资源的 DELETE . 删除后,任何人都无法再访问该资源的内容 . 'reason'不能包含指向已删除资源的超链接 . 要么,

    • You are trying to alter a resourcestate=activestate=deleted 使用 DELETE 方法 . 主API会忽略state = deleted的资源,但对于管理员或具有数据库访问权限的人员可能仍然可以读取 . 这是允许的 - DELETE 不必擦除资源的后备数据,只删除在该URI上公开的资源 .

    任何需要 DELETE 请求上的消息体的操作都可以分解为最常见的, POST 用消息体执行所有必要的任务,以及 DELETE . 我认为没有理由打破HTTP的语义 .

  • 11

    鉴于你的情况,我会采取其中一个以下方法:

    • Send a PUT or PATCH :由于需要删除原因,我推断删除操作是虚拟的 . 因此,我认为通过PUT / PATCH操作更新记录是一种有效的方法,即使它本身不是DELETE操作 .

    • Use the query parameters :资源uri未被更改 . 我实际上认为这也是一种有效的方法 . 您链接的问题是在缺少查询参数时讨论不允许删除 . 在您的情况下,如果未在查询字符串中指定原因,我将只有默认原因 . 资源仍然是 resource/:id . 您可以使用资源上的链接标头为每个原因(在每个原因上使用 rel 标记来识别原因)使其可被发现 .

    • Use a separate endpoint per reason :使用类似 resource/:id/canceled 的网址 . 这确实改变了Request-URI,绝对不是RESTful . 同样,链接 Headers 可以使这个可被发现 .

    请记住,REST不是法律或教条 . 将其视为指导 . 因此,如果不遵循问题域的指导是有意义的,请不要这样做 . 只需确保您的API使用者了解差异 .

  • 36

    我建议您将所需的元数据作为URI层次结构本身的一部分 . 一个例子(天真):

    如果您需要根据日期范围删除条目,而不是将开始日期和结束日期作为正文或查询参数传递,请构造URI,以便将所需信息作为URI的一部分传递 .

    例如

    DELETE /entries/range/01012012/31122012 - 删除2012年1月1日至2012年12月31日之间的所有条目

    希望这可以帮助 .

相关问题