[英]REST API design: different granularity for receiving and updating resources
I'm in the process of creating a REST API. 我正在创建REST API。 Among others, there is a resource-type called
company
which has quite a lot of attributes/fields. 其中,有一种名为
company
的资源类型,它具有相当多的属性/字段。
The two common use cases when dealing with company
resources are: 处理
company
资源时的两个常见用例是:
I came up with two different approaches regarding the design of the API and need to pick one of them (maybe there are even better approaches, so feel free to comment): 我提出了两种不同的API设计方法,需要选择其中一种方法(可能还有更好的方法,所以请随意评论):
1. Using subresources for fine-grained updates 1.使用子资源进行细粒度更新
Since the attributes of a company can be grouped into categories (eg street, city and state represent an address... phone, mail and fax represent contact information and so on...), one approach could be to use the following routes: 由于公司的属性可以分为不同类别(例如街道,城市和州代表地址......电话,邮件和传真代表联系信息等等),一种方法可以是使用以下路线:
/company/id
: can be used to fetch a whole company using GET
/company/id
:可用于使用GET
获取整个公司
/company/id/address
: can be used to update address information (street, city...) using PUT
/company/id/address
:可用于使用PUT
更新地址信息(街道,城市......)
/company/id/contact
: can be used to update contact information (phone, mail...) using PUT
/company/id/contact
:可用于使用PUT
更新联系信息(电话,邮件...)
And so on. 等等。
But: Using GET
on subresources like /company/id/address
would never happen. 但是:在
/company/id/address
这样的子资源上使用GET
永远不会发生。 Likewise, updating /company/id
itself would also never happen (see use cases above). 同样,更新
/company/id
本身也永远不会发生(参见上面的用例)。 I'm not sure if this approach follows the idea of REST since I'm loading and manipulating the same data using different URLs. 我不确定这种方法是否遵循REST的思想,因为我使用不同的URL加载和操作相同的数据。
2. Using HTTP PATCH for fine-grained updates 2.使用HTTP PATCH进行细粒度更新
In this approach, there are no extra routes for partial updates. 在这种方法中,没有用于部分更新的额外路由。 Instead, there is only one endpoint:
相反,只有一个端点:
/company/id
: can be used to fetch a whole company using GET
and, at the same time, to update a subset of the resource (address, contact info etc.) using PATCH
. /company/id
:可用于使用GET
获取整个公司,同时使用PATCH
更新资源的子集(地址,联系信息等)。
From a technical point of view, I'm quite sure that both approaches would work fine. 从技术角度来看,我很确定这两种方法都能正常工作。 However, I don't want to use REST in a way that it isn't supposed to be used.
但是,我不想以不应该使用的方式使用REST。 Which approach do you prefer?
你更喜欢哪种方法?
Do you really nead each and every field contained in the GET
response all the time? 您是否真的知道
GET
响应中包含的每个字段? If not, than its more than just fine to create own resources for addresses and contacts. 如果没有,那么为地址和联系人创建自己的资源不仅仅是好的。 Maybe you will later find a further use-case where you might reuse these resources.
也许您稍后会找到一个可以重用这些资源的进一步用例。
Moreover, you can embed other resources as well in resources. 此外,您还可以在资源中嵌入其他资源。 JSON HAL ( hal-json ) fe explicitely provides an
_embedded
property where you can embed the current state of fe sub-resources. JSON HAL ( hal-json )fe明确地提供了一个
_embedded
属性,您可以在其中嵌入fe子资源的当前状态。 A simplified HAL-like JSON representation of an imaginary company resource with embedded resources could look like this: 具有嵌入资源的虚构公司资源的简化类似HAL的JSON表示可能如下所示:
{
"name":"Test Company",
"businessType":"PLC",
"foundingYear": 2010,
"founders": [
{
"name": "Tim Test",
"_links": {
"self": {
"href": "http://example.org/persons/1234"
}
}
}
],
...
"_embedded": {
"address": {
"street": "Main Street 1",
"city": "Big Town",
"zipCode": "12345",
"country": "Neverland"
"_links": {
"self": {
"href": "http://example.org/companies/someCompanyId/address/1"
},
"googleMaps": {
"href": "http://maps.google.com/?ll=39.774769,-74.86084"
}
}
},
"contacts": {
"CEO": {
"name": "Maria Sample",
...
"_links": {
"self": {
"href": "http://example.org/persons/1235"
}
}
},
...
}
}
}
Updating embedded resources therefore is straigtforward by sending a PUT
request to the enclosed URI of the particluar resource. 因此,通过向特定资源的封闭URI发送
PUT
请求,可以更新嵌入式资源。 As GET
requests my be cached, you might need to provide finer grained caching settings (fe with conditional GET requests aka If-Modified-Since
or ETAG header fields) to retrieve the actual state after an update. 由于
GET
请求我被缓存,您可能需要提供更细粒度的缓存设置(带有条件GET请求,也就是If-Modified-Since
或ETAG头字段)来检索更新后的实际状态。 These headers should consider the whole resource (incl. embedded once) in order to return the updated state. 这些头应该考虑整个资源(包括嵌入一次)以返回更新的状态。
PUT
vs. PATCH
for "partial updates": PUT
与PATCH
的“部分更新”: While the semantics of PUT
are rather clear, PATCH
is often confused with a partial update by just sending the new state for some properties to the service. 虽然
PUT
的语义相当清楚,但PATCH
通常只是通过向服务发送某些属性的新状态而与部分更新混淆。 This article however describes what PATCH
really should do. 然而, 本文描述了
PATCH
应该做什么。
In short, for a PATCH
request a client is responsible for comparing the current state of a resource and calculating the necessary steps to transform the current resource to the desired state. 简而言之,对于
PATCH
请求,客户端负责比较资源的当前状态并计算将当前资源转换为期望状态的必要步骤。 After calculating the steps, the request will have to contain instructions the server has to understand to execute these instructions and therefore produces the updated version. 在计算步骤之后,请求必须包含服务器必须理解的指令才能执行这些指令,从而产生更新的版本。 A
PATCH
request is furthermore atomic - either all instructions succeed or none. 此外,
PATCH
请求是原子的 - 要么所有指令都成功,要么无。 This adds some transaction requirements to this request. 这会为此请求添加一些事务要求。
In this particular case I'd use PATCH
instead of subresources approach. 在这种特殊情况下,我使用
PATCH
而不是子资源方法。 First of all this isn't a real subresources. 首先,这不是一个真正的子资源。 It's just a fake abstraction introduced to eliminate the problem of updating the whole big entity (resource).
这只是为了消除更新整个大实体(资源)的问题而引入的虚假抽象。 Whereas
PATCH
is a REST compatible, well established and common approach. 而
PATCH
是REST兼容,成熟且通用的方法。
And (IMO ultima ratio ), imagine that you need to extend company somehow (by adding magazine, venue, CTO, whatever). 和(IMO 最终比率 ),想象你需要以某种方式扩展公司(通过添加杂志,场地,CTO,等等)。 Will you be adding a new endpoint to enable client to update this newly-added part of a resource?
您是否要添加新端点以使客户端能够更新此新添加的资源部分? How it finishes?
怎么结束? With multiple endpoint that no one understands.
具有无人理解的多个端点。 With
PATCH
your API is ready for new elements of a company. 使用
PATCH
您的API已准备好用于公司的新元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.