我们有一个库存功能,我们可以在其中生成账单。有一个编辑账单 API 调用。我们很困惑将其实现为 PATCH 或 PUT。
假设我们的账单行项目由
{
stockId
quantity
rate
}
ID = 1 的账单有 2 个行项目:
| Stock Id | Qty | Rate |
| 10 | 2 | 10 |
| 11 | 3 | 20 |
现在假设我想更改quantity for stock Id : 10 to 5
和 我想更改rate for stock Id : 11 to 40
我是否应该将其表示为PUT调用,例如:
bill : {
id : 1
lineItems : [
{
stockId : 10,
qty : 5,
rate : 10
},
{
stockId : 11,
qty : 3,
rate : 40
}
]
}
我是否应该将其表示为PATCH调用,例如:
bill : {
id : 1
lineItems : [
{
stockId : 10,
qty : 5,
},
{
stockId : 11,
rate : 40
}
]
}
还有其他参数,如折扣类型,折扣值作为BillLineItem的一部分,我在上面的例子中没有显示。
维基百科描述了HTTP方法对应于RESTful操作的典型方式:
PUT
- 将集合资源的成员资源的所有表示形式替换为请求正文中的表示形式,或者创建集合资源(如果不存在(。PATCH
- 使用请求正文中的说明更新集合资源的成员资源的所有表示形式,或者如果集合资源不存在,则可以创建集合资源。
由于您要更新帐单项的各个属性,而不是完全替换它们,因此PATCH
是合适的方法。
我们很困惑地将其实现为 PATCH 或 PUT。
PUT 和 PATCH 都具有远程创作语义;松散地说,这两者都是请求服务器更改其资源副本以具有与客户端副本相同的表示形式。
PUT
是直接的"使您的副本像我在此请求中包含的副本一样"。PATCH
是"将这些更改应用于您的副本"。
因此,PUT
是幂等的;同一请求的两个副本与请求的单个副本具有相同的效果。 这种语义提示在不可靠的网络上可能很重要 - 如果PUT
请求丢失,我们可以重新发送它。 此外,重新发送消息是安全的提示既是标准的,又包含在消息本身中;这意味着任何看到消息的通用组件都会知道重新发送是安全的。
PATCH
没有内置的幂等语义 - 如果消息丢失,通用组件不知道请求是否可以安全地重复,因此它需要失败,而不是重试。
这对PUT
来说是一个相当大的胜利。
但是,当资源非常大(意味着比 HTTP 标头大得多(并且您所做的更改的大小很小时,仅将修订发送到表示形式而不是整个内容可能是有意义的。 在这种情况下,使用PATCH
可能是更好的选择。
REST的部分意义在于我们使用"易于标准化的形式"进行通信,因此在可能的情况下,您应该更喜欢支持标准化的补丁文档格式(application/json-patch+json,或application/merge-patch+json(,而不是发明自己的定制表示。