DELETE请求正文的RESTful替代方法
虽然HTTP 1.1规范似乎允许 DELETE请求上的消息体,但似乎表明服务器应该忽略它,因为没有定义它的语义。
4.3消息体
服务器应该读取并转发任何请求的消息体; 如果请求方法不包含实体主体的定义的语义,那么在处理请求时应该忽略消息主体。
我已经回顾了几个关于这个主题的相关讨论,比如:
- 允许HTTP DELETE请求的实体主体?
- HTTP请求方法的有效载荷
- 带请求正文的HTTP GET
大多数讨论似乎都认为可以允许在DELETE上提供消息正文,但通常不推荐使用。
此外,我已经注意到各种HTTP客户端库中的趋势,越来越多的增强function似乎被logging在这些库中以支持DELETE上的请求体。 大多数图书馆似乎有责任,虽然偶尔有一点点的初步阻力。
我的用例需要在DELETE上添加一些必需的元数据(例如删除的“原因”以及删除所需的其他一些元数据)。 我已经考虑了以下选项,其中没有一个看起来完全合适,并且与HTTP规范和/或REST最佳实践一致:
- 消息体 – 规范表明DELETE上的消息体没有语义值; HTTP客户端不完全支持; 不是标准的做法
- 自定义HTTP标头 – 要求自定义标头通常违反标准做法 ; 使用它们与我的API的其余部分不一致,其中没有一个需要自定义标题; 此外,没有好的HTTP响应可用于指示不良的自定义标头值(可能完全是一个单独的问题)
- 标准HTTP头 – 没有标准头是适当的
- 查询参数 – 添加查询参数实际上改变了被删除的Request-URI; 违反标准做法
- POST方法 – (例如
POST /resourceToDelete { deletemetadata }
)POST不是删除的语义选项; POST实际上代表所需的相反的动作(即POST创build资源下属;但我需要删除资源) - 多个方法 – 将DELETE请求分成两个操作(例如,PUT删除元数据,然后删除)将primefaces操作拆分为两个操作,可能会导致不一致的状态。 删除原因(和其他相关的元数据)不是资源表示本身的一部分。
我的第一select可能是使用邮件正文,其次是自定义的HTTP头; 然而,如上所述,这些方法有一些缺点。
是否有任何build议或最佳做法与REST / HTTP标准一起在DELETE请求中包含所需的元数据? 有没有其他的select,我没有考虑?
尽pipe一些build议不要使用DELETE请求的消息正文,但在某些使用情况下,这种方法可能是合适的。 这是我们在评估问题/答案中提到的其他选项之后,以及在与服务消费者合作之后最终使用的方法。
虽然消息体的使用并不理想,但其他选项都不是完美的。 请求主体DELETE使我们能够轻松,清楚地将附加数据/元数据的语义添加到DELETE操作所需的附加数据/元数据中。
我仍然愿意接受其他的想法和讨论,但是想要closures这个问题的循环。 我感谢大家对这个话题的思考和讨论!
你似乎想要的是两件事之一,这两件事都不是一个纯粹的DELETE
:
- 你有两个操作,一个是删除原因,然后是
DELETE
资源。 一旦被删除,资源的内容不再被任何人访问。 “原因”不能包含指向已删除资源的超链接。 要么, - 您正尝试通过使用
DELETE
方法将资源从state=active
更改为state=deleted
。 状态=已删除的资源将被主API忽略,但对于具有数据库访问权限的pipe理员或某人仍然可读。 这是允许的 –DELETE
不必删除资源的后备数据,只能删除在该URI处公开的资源。
任何需要DELETE
请求上的消息体的操作都可以被分解成最常用的POST
,用消息体和POST
来完成所有必要的任务。 我没有理由打破HTTP的语义。
鉴于你的情况,我会采取以下方法之一:
- 发送一个PUT或PATCH :我推断删除操作是虚拟的,由于需要删除的原因。 因此,我相信通过PUT / PATCH操作更新logging是一种有效的方法,即使它本身不是DELETE操作。
- 使用查询参数 :资源URI不被更改。 我其实认为这也是一个有效的方法。 你链接的问题是谈论如果查询参数丢失,不允许删除。 在你的情况下,如果原因没有在查询string中指定,我只是有一个默认的原因。 资源仍然是
resource/:id
。 你可以通过资源上的Link标题来查找每个原因(每个标签上都有一个rel
标签来标识原因)。 - 每个理由使用一个单独的端点 :使用像
resource/:id/canceled
的URL。 这实际上改变了Request-URI,绝对不是RESTful。 同样,链接头可以使这个发现。
请记住,REST不是法律或教条。 把它看作指导。 所以,当不遵循问题领域的指导意义时,不要这么做。 只要确保你的API消费者被告知方差。
我build议你包含所需的元数据作为URI层次本身的一部分。 一个例子(天真):
如果您需要删除基于date范围的条目,而不是以正文或查询参数的forms传递开始date和结束date,则应将URI构造为将所需信息作为URI的一部分传递。
例如
DELETE /entries/range/01012012/31122012
– 删除2012年1月1日至2012年12月31日之间的所有条目
希望这可以帮助。