为嵌套资源设计rest api

Posted

技术标签:

【中文标题】为嵌套资源设计rest api【英文标题】:Designing rest api for nested resources 【发布时间】:2021-09-02 01:38:01 【问题描述】:

我的系统中有以下资源 1. 服务 2. 功能具有以下 JSON 结构的功能,


 id: "featureName",
 state: "active",
 allowList: [serviceID1, serviceID2],
 denyList: [serviceID3, serviceID4]

我正在尝试更新由 serviceID 组成的允许列表或拒绝列表,并考虑使用 PATCH 方法进行如下操作,

/features/featureId/allowlist 
/features/featureId/denylist 
/features/featureName/state/state

我的第一个问题是我是否应该在 url 中包含允许列表、状态、拒绝列表,因为我的资源是服务和功能,而不是允许列表或拒绝列表。

其余端点应该是什么样子? 在阅读了下面提到的线程后,我正在考虑重组网址如下,

/features/featureId

[
     "op": "add", "path": "/allowList", "value": [ "serviceA", "serviceB"],
     "op": "update", "path": "/state", "value": false
]

最后,在这里使用 PATCH 是否合理?或者有更好的方法来设计api。

注意:我从线程REST design for update/add/delete item from a list of subresources得到了一些帮助,但没有经常使用补丁。

【问题讨论】:

【参考方案1】:

其余端点应该是什么样子?

用于编辑(PUT、PATCH)资源的 URI 应该与用于读取(GET)资源的 URI 相同。这个设计的动机是cache-invalidation;您的成功写入会自动使之前缓存的相同资源(相同 URI)读取无效。

最后,在这里使用 PATCH 是否合理?或者有更好的方法来设计api。

在此示例中,与 HTTP 标头相比,文档的表示很小,并且补丁文档的大小接近资源表示的大小。如果这是典型情况,我会倾向于使用 PUT 而不是 PATCH。 PUT 具有idempotent 语义,通用组件可以利用该语义(例如,当对较早请求的响应在网络上丢失时自动重新发送请求)。


GET /features/1 by user1 
PUT /features/1 //done by user 2 
PUT /features/1 //done by user1 

user2 的 PUT 对 user1 不可见,并且 user1 将更新旧对象的状态(id=1)在这种情况下可以做什么?

Conditional Requests.

您安排这样的事情:(a) 来自服务器的 GET 请求包括标识表示的validators (b) 当请求缺少条件标头时服务器响应 428 Precondition Required (c) 客户端知道读取验证器来自资源元数据,并在提交 PUT 请求时使用正确的条件标头 (d) 服务器知道在接受新表示之前将验证器与当前表示进行比较。

【讨论】:

假设动作顺序是, GET /features/1 //由用户1完成 PUT /features/1 //由用户2完成 PUT /features/1 //由用户1完成 由用户2完成user1 将不可见,并且 user1 将更新旧对象的状态(id=1)在这种情况下可以做什么? 查看新添加的关于条件请求的讨论。

以上是关于为嵌套资源设计rest api的主要内容,如果未能解决你的问题,请参考以下文章

RESTful API URI 设计

Restful API 的设计规范(转)

10个有关RESTful API良好设计的最佳实践

理解RESTful Api设计

Restful API

API设计RESTful API 设计指南