上述扩展 API 是否好/推荐?
可能不会。
HTTP(除其他外)是关于消息语义的协议:关于消息含义的统一协议。
基本目标是,由于每个人都对消息的含义有相同的理解,我们可以使用许多通用组件(浏览器、反向代理等)。
当我们开始尝试以非标准方式处理消息时,我们就失去了通用接口的好处。
就 DELETE 而言,您的用例遇到了一个问题,即 HTTP 没有定义 参数化 DELETE。
在 HTTP 消息中放置参数的通常位置是在消息正文中。可惜……
DELETE 请求消息中的有效负载没有定义的语义;在 DELETE 请求上发送有效负载正文可能会导致某些现有实现拒绝该请求
换句话说,您不能指望通用组件在这里做正确的事情,因为请求正文超出了范围。
另一方面
DELETE /resources/{resourceId}?backupBeforeDelete=true
这存在通用组件无法识别/resources/{resourceId}?backupBeforeDelete=true 与/resources/{resourceId} 是相同 资源的问题。两者的标识符不同,发送给一个的消息不会影响另一个。
对于您的用例,正确的答案是更改您的方法令牌;您在这里尝试执行的正确标准方法是 POST
POST 在 HTTP 中有许多有用的用途,包括“此操作不值得标准化”的一般用途。 -- Fielding, 2009
您应该使用资源的“真实”URI(与 GET 请求中使用的相同),并将您需要的任何参数粘贴到有效负载中。
POST /resources/{resourceId}
backupBeforeDelete=true
假设您将 POST 用于其他“不值得标准化”的操作,则请求中需要有足够的上下文,以便服务器可以区分不同的用例。在网络上,我们通常会通过 HTML 表单收集参数,通常的答案是在正文中包含请求令牌
POST /resources/{resourceId}
action=delete&backupBeforeDelete=true
另一方面,如果你认为你正在处理一个值得标准化的动作,那么正确的做法是定义一个具有你想要的语义的新方法标记,并推动采用
MAGIC_NEW_DELETE /resources/{resourceId}
backupBeforeDelete=true
这毕竟是PATCH 的来源; Dusseault 等人认识到补丁语义可能对所有资源都有用,因此创建了一个描述他们想要的语义的文档,并通过标准化过程引导该文档。