Web services RESTAPI设计:接收和更新资源的不同粒度

Web services RESTAPI设计:接收和更新资源的不同粒度,web-services,api,rest,http,web,hal-json,Web Services,Api,Rest,Http,Web,Hal Json,我正在创建一个RESTAPI。除此之外,还有一种叫做company的资源类型,它有很多属性/字段 处理公司资源时的两个常见用例是: 用一个请求加载整个公司及其所有属性 更新公司的一组(相对较小)属性,但决不能同时更新所有属性 关于API的设计,我提出了两种不同的方法,需要从中选择一种(可能还有更好的方法,请随意评论): 1。使用子资源进行细粒度更新 由于公司的属性可以分为多个类别(例如,街道、城市和州代表地址……电话、邮件和传真代表联系信息等……),因此一种方法可以使用以下路线: /com

我正在创建一个RESTAPI。除此之外,还有一种叫做
company
的资源类型,它有很多属性/字段

处理
公司
资源时的两个常见用例是:

  • 用一个请求加载整个公司及其所有属性
  • 更新公司的一组(相对较小)属性,但决不能同时更新所有属性
关于API的设计,我提出了两种不同的方法,需要从中选择一种(可能还有更好的方法,请随意评论):


1。使用子资源进行细粒度更新

由于公司的属性可以分为多个类别(例如,街道、城市和州代表地址……电话、邮件和传真代表联系信息等……),因此一种方法可以使用以下路线:

/company/id
:可以使用
GET

/company/id/address
:可以使用
PUT

/company/id/contact
:可以使用
PUT

等等

但是:在
/company/id/address
这样的子资源上使用
GET
是永远不会发生的。同样,更新
/company/id
本身也永远不会发生(参见上面的用例)。我不确定这种方法是否遵循REST的思想,因为我使用不同的URL加载和操作相同的数据

2。使用HTTP修补程序进行细粒度更新

在这种方法中,不存在用于部分更新的额外路由。相反,只有一个端点:

/company/id
:可以使用
GET
获取整个公司,同时使用
PATCH
更新资源的子集(地址、联系信息等)



从技术角度来看,我非常确信这两种方法都可以很好地工作。然而,我不想以不应该使用REST的方式使用REST。你喜欢哪种方法

在这种特殊情况下,我将使用
补丁
而不是子资源方法。首先,这不是一个真正的子资源。它只是一个伪抽象,用于消除更新整个大实体(资源)的问题。然而,
PATCH
是一种与REST兼容、成熟且通用的方法


和(IMO ultima ratio),想象一下你们需要以某种方式扩展公司(通过添加杂志、场地、CTO等等)。您是否要添加一个新的端点,以使客户端能够更新资源的这个新添加的部分?它是怎么结束的?具有无人理解的多个端点。使用
补丁
您的API就可以为公司的新元素做好准备。

您真的一直在整理
获取
响应中包含的每个字段吗?如果没有,那么为地址和联系人创建自己的资源就远远不够了。也许您以后会发现一个进一步的用例,您可以在其中重用这些资源

此外,还可以在资源中嵌入其他资源JSON HAL()f.e.明确提供了一个
\u embedded
属性,您可以在其中嵌入f.e.子资源的当前状态。带有嵌入式资源的虚拟公司资源的简化HAL-like JSON表示可能如下所示:

{
“名称”:“测试公司”,
“业务类型”:“PLC”,
“创立年”:2010年,
“创始人”:[
{
“名称”:“Tim测试”,
“_链接”:{
“自我”:{
“href”:”http://example.org/persons/1234"
}
}
}
],
...
“_嵌入式”:{
“地址”:{
“街道”:“主街1号”,
“城市”:“大城市”,
“zipCode”:“12345”,
“国家”:“梦幻岛”
“_链接”:{
“自我”:{
“href”:”http://example.org/companies/someCompanyId/address/1"
},
“谷歌地图”:{
“href”:”http://maps.google.com/?ll=39.774769,-74.86084"
}
}
},
“联系人”:{
“首席执行官”:{
“姓名”:“玛丽亚样本”,
...
“_链接”:{
“自我”:{
“href”:”http://example.org/persons/1235"
}
}
},
...
}
}
}
因此,通过向特定资源的封闭URI发送
PUT
请求,可以提前更新嵌入式资源。由于
GET
需要缓存我的请求,您可能需要提供更细粒度的缓存设置(例如,如果在
或ETAG头字段之后修改了条件GET请求,则称为
),以检索更新后的实际状态。这些报头应该考虑整个资源(包括嵌入一次)以返回更新的状态。
关于“部分更新”的
PUT
PATCH
: 虽然
PUT
的语义相当清楚,
PATCH
通常与部分更新混淆,只将某些属性的新状态发送给服务。然而,描述了
补丁
真正应该做什么

简而言之,对于
补丁
请求,客户端负责比较资源的当前状态,并计算将当前资源转换为所需状态的必要步骤。在计算步骤之后,请求必须包含服务器必须理解的指令,以执行这些指令,从而生成更新版本。此外,
补丁
请求是原子性的