我有一个 API 来创建订单
POST /api/order
并检索订单 GET /api/order/{order_id
}。
我还有一个 PATCH 方法来部分更新订单
PATCH /api/order/{order_id}
。
打补丁后,如果用户将 order_status 更新为 “Built”,我想执行一些额外的逻辑。例如,发送电子邮件、使用构建的实体在另一个表中创建记录等等。
我的问题是,解决这种情况的平安标准是什么?我应该创建一个新的 API 来执行此操作吗?像
POST /api/order/{order_id}/build
这样的东西会用 “Built” 的 order_status 更新订单对象,然后执行添加工作流程?或者我的补丁应该处理状态更新并进行额外的 API 调用来执行其余操作吗?
属性更改对 PATCH 等非安全方法产生副作用当然是可以的,这可能是合理的做法。业务逻辑应该主要由服务器拥有,因此依赖客户端发出另一个请求似乎没有任何目的。
但是,使用
POST
来启动某些进程也可以。
推荐:回顾Webber 2011。
我的问题是,解决这种情况的平安标准是什么。
不,因为我们真的不需要。
HTTP 请求属于网络文档传输域;它们具有获取或操作资源模型的语义。您的实施如何做到这一点是您自己的事。
换句话说,有用的工作是处理操作资源的请求的“副作用”。 因此,如果您想启动一堆业务流程,因为有人向您发送了描述状态标志更改的补丁文档,那就
很好。
当前PATCH 参考是RFC 5789
服务器必须以原子方式应用整套更改,并且绝不提供(例如,在此操作期间响应 GET)部分修改的表示。如果整个补丁文档无法成功应用,则服务器不得应用任何更改。因此,您需要仔细考虑如何将补丁“应用”到资源的表示中。
非常粗略地说,PATCH 的语义本质上就是我们想要远程创作原始“文档”的语义。例如,我们可以通过向 Web 服务器发送补丁文档来修复网页上的拼写错误,并且服务器的实现将应用整个补丁或不应用任何补丁。
REST 的统一接口约束表明,无论资源的底层实现是什么,这些语义都应该相同。
因此,如果您的实现无法满足 PATCH 的原子性约束,您必须 (a) 接受您的实现对由此导致的任何属性丢失负责,或者 (b) 从该资源支持的方法列表中删除 PATCH。
发送 PATCH 请求的一个完全有效的替代方法是发送 POST 请求:
POST /api/order/12345
Content-Type: text/plain
Bob,
Please change the order_status to "Built"
从 REST/HTTP 角度来看,这很好
。您可能需要在实现中做更多工作(以区分此 POST 与针对同一资源的其他 POST 请求消息)。 向通过成功处理请求而更改的主要资源发送 POST 请求,可以让您利用 HTTP 中内置的
通用缓存失效很好
POST /api/order/12345/build
Content-Type: text/plain
Bob,
Do it.
这样就可以了;它只是不像以前的替代方案那样对缓存友好。欢迎来到权衡的世界。
只有当额外的仪式让你关心的某些人(你的客户、你的运营团队、你的文档团队,等等)的事情变得明显更好时,我才会这样做。
添加仪式来满足人为的约束是浪费。