在REST Api调用中批量更新集合的最佳实践 [英] Best practice to batch update a collection in a REST Api call

查看:486
本文介绍了在REST Api调用中批量更新集合的最佳实践的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找API设计的最佳做法,以通过API调用批量更新集合.

我的收藏夹具有URL/api/v1/cars,我想更新收藏夹中的所有汽车,以添加当前时间的时间戳.

{
    data: [
    {
        manufacturer: 'Porsche',
        timestamp: ...
    },
    {
        manufacturer: 'BMW',
        timestamp: ...
    }
    {
        manufacturer: 'Peugeot',
        timestamp: ...
    }
}

我考虑了几种选择,但我不知道最佳做法是什么.

应该是:

1/建模为另一个资源,例如POST api/v1/cars/updateTimestamp

2/作为查询参数传递:PUT api/v1/cars?updateTimestamp

3/传递请求的正文:

POST api/v1/cars 
{"operation":"Update timestamps"}

我想强调的是,整个处理过程应在后端完成,而不应由客户端传递. 对于后端发生的任何复杂处理,也会发生相同的问题. 在这种情况下,如何保持API RESTy.

非常感谢您的帮助/任何指向相关资源的指针.

解决方案

由于HTTP中没有定义部分PUT,因此您需要为每个资源发送整个实体以进行更新或使用其他操作.

POST

由于POST是万能的操作,因此您可以使用它在服务器上创建短暂的临时资源(甚至不必具有

此方法的优点是,即使不事先了解当前状态,也可以随时将其发送到服务器.但是,这也存在某些条目被更新的危险,这些条目不应该受到影响.这可以通过指定If-Match标头来实现,该标头指向某个版本哈希并在每次实体更新时更改,或者通过向服务器也必须理解的JSON主体添加某个限制器来实现.

PATCH

POST类似,POST可以将任何内容发送到服务器,PATCH用于修改资源.单个请求可以显式地一次更新多个资源,但是,客户端需要定义将资源从状态A转换为状态B的必要步骤.因此,客户端也需要具有资源的最新状态才能成功将资源转换为最新状态(-> ETag和If-Modified HTTP标头)

因此,对于提供的示例,

一个 JSON补丁请求可能看起来像这样:

PATCH /api/v1/cars HTTP/1.1
Host: example.org
Content-Length: 215
Content-Type: application/json-patch+json
If-Match: "abc123"

[
  { "op": "add", "path": "/data/1", "value": [ "timestamp", "..." ] },
  { "op": "add", "path": "/data/2", "value": [ "timestamp", "..." ] },
  { "op": "add", "path": "/data/3", "value": [ "timestamp", "..." ] }
]

其中/data/1/data/2/data/3PorscheBMWPeugeot的资源的唯一标识符.

PATCH指定请求必须是原子的,这意味着全部或全部指令都不会成功,这也给表带来了一些交易要求.

讨论

如前所述,在POST请求中,至少可以在服务器能够理解您要发送的内容的情况下,向服务器发送您想要的任何内容.因此,由您决定如何设计请求结构(以及服务器逻辑).

另一方面,

PATCH(尤其是JSON Patch)定义了一些严格的规则和预定义的操作,通常是针对传统修补的.交易需求既可以是负担,也可以是收益.除此之外,PATCH尚未最终确定,尽管已被广泛使用,但仍在RFC中.

Hi I'm looking for best practices with API design to batch update a collection with an API call.

My collection has URL /api/v1/cars and I would like to update all the cars in the collection to add a timestamp of the current time.

{
    data: [
    {
        manufacturer: 'Porsche',
        timestamp: ...
    },
    {
        manufacturer: 'BMW',
        timestamp: ...
    }
    {
        manufacturer: 'Peugeot',
        timestamp: ...
    }
}

I thought about a few options but I can't figure what is the best practice.

Should it be:

1/ Modelled as another resource such as POST api/v1/cars/updateTimestamp

2/ Passed as a query parameter: PUT api/v1/cars?updateTimestamp

3/ Pass in the body of the request:

POST api/v1/cars 
{"operation":"Update timestamps"}

I'd like to emphasize that the whole processing should be done on the back-end and not passed by the client. Same problem would happen for any complex processing that happens on the back end.. How could I keep the API RESTy in this case.

Thanks a lot for your help/any pointer to relevant ressources.

解决方案

As there is no partial PUT defined in HTTP, you either need to send the whole entity for each resource to update or use some other operations.

POST

As POST is an all-purpose operation you can use it to create a short-living temporary resource at the server (which further does not even have to have an own URL). On receipt the server can update either all specified entries or all entries in general with some provided field-value combination (certain table alterering may be necessary though if the column is not yet know in relational databases)

A simple request may look like this:

POST /api/v1/cars/addAttributes HTTP/1.1
Host: example.org
Content-Length: 24
Content-Type: application/json
If-Match: "abc123"

{
  "timestamp": "..."
}

This approach has the advantage that it could be sent to the server anytime, even without prior knowledge of the current state. This, however, also has the danger that certain entries get updated which shouldn't be affected. This can either be influenced by specifying an If-Match header, which points to a certain version-hash and is changed on every entity update, or by adding a certain restrictor to the JSON body which the server also has to understand.

PATCH

Similar to POST, which can literally send anything to the server, PATCH is intended for modification of resources. A single request explicitely may update multiple resources at once, however, the client needs to define the necessary steps to transform the resources from state A to state B. Therefore, the client also needs to have the latest state of the resource in order to successfully transform the resource to its newest state (-> ETag and If-Modified HTTP headers)

A JSON Patch request for the provided example may therefore look like this:

PATCH /api/v1/cars HTTP/1.1
Host: example.org
Content-Length: 215
Content-Type: application/json-patch+json
If-Match: "abc123"

[
  { "op": "add", "path": "/data/1", "value": [ "timestamp", "..." ] },
  { "op": "add", "path": "/data/2", "value": [ "timestamp", "..." ] },
  { "op": "add", "path": "/data/3", "value": [ "timestamp", "..." ] }
]

Where /data/1, /data/2 and /data/3 are the unique identifiers for the resources of Porsche, BMW and Peugeot.

PATCH specifies that a request has to be atomic which means that either all or none of the instructions succeed which also brings some transaction requirements to the table.

Discussion

As already mentioned, in POST requests you can literally send anything you want to the server at least as long as the server is capable of understanding what you are sending. It is therefore up to you how you design the request structure (and the server logic as well).

PATCH on the other hand, especially with JSON Patch defines some strict rules and predefined operations typically to traditional patching. The transaction requirement can be a burden but also a benefit. In addition to that, PATCH is not yet final and still in RFC though it is already widely available.

这篇关于在REST Api调用中批量更新集合的最佳实践的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆