用于状态更改的 REST 动词 - 我们可以就 POST 达成一致吗?
Posted
技术标签:
【中文标题】用于状态更改的 REST 动词 - 我们可以就 POST 达成一致吗?【英文标题】:REST verb for state change - can we agree on POST? 【发布时间】:2019-01-16 10:49:20 【问题描述】:如何通过 FSM 状态更改最好地扩展 REST?
没有人可以知道状态变化是否是幂等的,所以最明智的做法可能是假设它们不是,并且作为一般规则使用 POST,好吗?
对我和我的发现来说,POST 比 PUT 或 PATCH 更有意义。
POST /coffeemachines/id/start
或者可能更冗长?
POST /coffeemachines/id/state/start
虽然 start 看起来像一个动词(违反 REST 实践),但我认为它不是:
主要动词是戳 POST,我们想要改变状态。 start 只是请求的状态更改的属性值。我想我不是第一个登上月球的人,感谢任何参考或想法。
【问题讨论】:
您可能会发现这很有用 - ***.com/questions/17529315/… 【参考方案1】:状态变化的 REST 动词 - 我们可以就 POST 达成一致吗?
REST 的参考实现是万维网,尽管 html(主要媒体类型)仅指定支持 GET
和 POST
,但它却取得了灾难性的成功。
将POST
用于不安全操作很好。
虽然 start 看起来像一个动词(违反 REST 实践)
不——REST 不关心 URI 的拼写。这是重点的一部分:服务器可以随时更改链接中的 URI,因为客户端只需跟随链接。
也就是说,您建议的标识符存在问题,您可能需要考虑
/coffeemachines/id
/coffeemachines/id/start
就 REST 而言,这些是不同的资源。这意味着当您 POST
向 /coffeemachines/id/start
发出请求时,您本地缓存的 /coffeemachines/id
副本不是 invalidated。
如果您想利用已内置到可用域无关组件中的缓存支持,那么您希望POST
的目标与GET
的目标匹配:/coffeemachines/id
/coffeemachines/id/start
,在此设计中,不是POST
的目标,而是向/coffeemachines/id
提交启动消息的表单资源的标识符。同样,/coffeemachines/id/stop
将标识提交停止消息的表单资源。
当允许转换时,咖啡机的表示将包含指向这些表单的链接;例如,当咖啡机关闭时,GET
返回的咖啡机表示将包含指向开始表单的链接,但不包含指向停止表单的链接。
/coffeemachines/id/start
和 /coffeemachines/id/stop
与 /coffeemachines/id
是不同的资源,因此可能有自己的缓存策略。
当然,表单不是单独的资源要求 - 如果表单是 /coffeemachines/id
资源本身的表示的一部分,该机制也可以工作。
能否请您详细说明一下 POST 与 PATCH
我发现这个observation by Roy Fielding 帮助了我:
HTTP 并不试图要求 GET 的结果是安全的。它所做的是要求操作的语义是安全的,因此如果发生任何导致财产损失的事情,那是实现的错误,而不是接口或该接口的用户。
PATCH 的语义比POST 更严格;这意味着客户端(和通用组件)可以对正在发生的事情做出更强的假设。
所以在下面的例子中:
PATCH /foo HTTP/1.1
Content-Type: application/json-patch+json
POST /foo HTTP/1.1
Content-Type: application/json-patch+json
服务器可以以完全相同的方式处理这些消息。识别 PATCH 方法的客户端将认识到服务器上的不安全更改应该是全有或全无(“服务器必须以原子方式应用整个更改集......”)并且可以根据需要利用它,但是使用 POST,则缺少该附加约束并且无法假定。
PATCH 规范说明:
与 POST 的比较更加困难,因为 POST 的使用方式多种多样,并且可以包含 PUT 和类似 PATCH 的操作(如果服务器选择)。如果操作未以可预测的方式修改 Request-URI 标识的资源,则应考虑使用 POST 而不是 PATCH 或 PUT。
【讨论】:
我能否请您详细说明一下 POST 与 PATCH,因为我仍然对这里的任何正式规则感到困惑。例如,apihandyman.io/do-you-really-know-why-you-prefer-rest-over-rpc POST 和 PATCH 都适合状态更改,这对我来说毫无意义。 我不认为 Arnaud Lauret 的文章特别有效。如果你已经“明白”了,那么你可以在他写的东西中找到正确的含义。如果你不这样做,那么我认为它根本没有帮助。【参考方案2】:您可以使用仅包含新状态的 HTTP PATCH 发送部分更新请求。
PATCH /coffeemachines/id
status: "active"
根据Wikipedia:
PATCH 方法是 HTTP 协议支持的一种请求方法,用于对现有资源进行部分更改。 PATCH 方法提供了一个实体,其中包含要应用于使用 HTTP URI 请求的资源的更改列表。更改列表以 PATCH 文档的形式提供。
用连字符分隔路径中的单词也更具可读性。例如:
PATCH /coffee-machines/id
status: "active"
【讨论】:
我也考虑过这一点,但由于我不记得的原因丢弃了补丁。状态更改可以被视为 POST /statechange 中的“新”,但 PATCH 方法显然在资源上下文中更有意义。以上是关于用于状态更改的 REST 动词 - 我们可以就 POST 达成一致吗?的主要内容,如果未能解决你的问题,请参考以下文章