REST:使用一个请求更新多个资源 - 是标准还是要避免?

Mar*_*ten 62 rest json

一个简单的REST API:

  • GET:items/{id} - 返回具有给定id的项的描述
  • PUT:items/{id} - 更新或创建具有给定id的项目
  • DELETE:items/{id} - 删除具有给定id的项目

现在有问题的API扩展:

  • GET:items?filter - 返回与过滤器匹配的所有项ID
  • PUT:items - 更新或创建JSON有效内容描述的一组项目
  • [[ DELETE:items - 删除JSON有效负载描述的项目列表 ]] < - 不正确

我现在对DELETE和PUT操作回收功能感兴趣,可以通过PUT/DELETE项目/ {id}轻松访问.

问题:提供这样的API是否常见?

替代方案:在单一连接的时代发出多个请求的多个请求很便宜,并且由于更改成功或失败,但是在NOSQL数据库时代,即使请求处理已经消失,列表中的更改也可能已经发生,因此会更加原子化内部服务器或任何由于任何原因.

[UPDATE]

在考虑了白宫Web标准维基百科:REST示例之后,现在使用以下示例API:

一个简单的REST API:

  • GET:items/{id} - 返回具有给定id的项的描述
  • PUT:items/{id} - 更新或创建具有给定id的项目
  • DELETE:items/{id} - 删除具有给定id的项目

最佳资源API:

  • GET:items?filter - 返回与过滤器匹配的所有项ID
  • POST:items - 根据JSON有效内容的描述更新或创建一组项目

不支持和禁止PUT和DELETE on/items.

使用POST似乎可以成为在封闭资源中创建新项目而不替换但附加的技巧.

HTTP语义POST读取:

通过追加操作扩展数据库

PUT方法需要替换完整集合以返回HTTP语义PUT引用的等效表示:

给定表示的成功PUT将表明对该相同目标资源的后续GET将导致在200(OK)响应中返回等效表示.

[UPDATE2]

对于多个对象的更新方面似乎更加一致的替代方案似乎是PATCH方法.PUT和PATCH之间的区别在RFC 5789草案中描述为:

PUT和PATCH请求之间的差异反映在服务器处理封闭实体以修改Request-URI标识的资源的方式中.在PUT请求中,封闭的实体被认为是存储在源服务器上的资源的修改版本,并且客户端正在请求替换所存储的版本.但是,对于PATCH,随附的实体包含一组指令,这些指令描述了如何修改当前驻留在源服务器上的资源以生成新版本.PATCH方法影响Request-URI标识的资源,它也可能对其他资源产生副作用; 即,可以通过应用PATCH来创建新资源,或者修改现有资源.

因此,与POST相比,PATCH也可能是一个更好的主意,因为PATCH允许UPDATE,因为POST只允许添加意味着添加而没有修改机会的东西.

所以POST在这里似乎是错误的,我们需要将我们提出的API更改为:

一个简单的REST API:

  • GET:items/{id} - 返回具有给定id的项的描述
  • PUT:items/{id} - 更新或创建具有给定id的项目
  • DELETE:items/{id} - 删除具有给定id的项目

最佳资源API:

  • GET:items?filter - 返回与过滤器匹配的所有项ID
  • POST:items - 按照JSON有效内容的描述创建一个或多个项目
  • PATCH:items - 根据JSON有效内容的描述创建或更新一个或多个项目

mah*_*off 41

你可以修补集合,例如

PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]
Run Code Online (Sandbox Code Playgroud)

从技术上讲,PATCH会识别URL中的记录(即PATCH /items/1而不是请求体中的记录,但这似乎是一个很好的实用解决方案.

为了支持在单个调用中删除,创建和更新,标准REST约定并不真正支持.一种可能性是一种特殊的"批处理"服务,它允许您将呼叫组合在一起:

POST /batch
[
  { method: 'POST', path: '/items', body: { title: 'foo' } },
  { method: 'DELETE', path: '/items/bar' }
]
Run Code Online (Sandbox Code Playgroud)

返回包含每个嵌入式请求的状态代码的响应:

[ 200, 403 ]
Run Code Online (Sandbox Code Playgroud)

不是很标准,但我已经完成了它的工作.


B12*_*ter 10

通过一个请求更新多个资源-是标准的还是要避免的?

好吧,有时候您只需要执行原子批处理操作或其他与资源相关的操作,而这些操作不适合简单的REST API的典型方案,但是如果需要,就无法避免。

是标准的吗?

没有普遍接受的REST API标准,因此很难回答这个问题。但是通过查看一些常用的api设计指南,例如jsonapi.orgrestfulapi.netmicrosoft api设计指南IBM的REST API约定,它们都没有提及批处理操作,您可以推断出这种操作通常不被理解为是REST API的标准功能。

也就是说,google api设计指南是一个例外,其中提到了创建“自定义”方法的方法,该方法可以使用冒号通过资源进行关联,例如https://service.name/v1/some/resource/name:customVerb,它还明确提到了批处理操作作为用例:

定制方法可以与资源,集合或服务相关联。它可以接受任意请求并返回任意响应,并且还支持流式请求和响应。自定义方法应使用HTTP POST动词,因为它具有最灵活的语义。对于性能至关重要的方法,提供自定义批处理方法以减少每个请求的开销可能很有用。

因此,在示例中,您根据Google的api指南执行了以下操作:

POST /api/items:batchUpdate
Run Code Online (Sandbox Code Playgroud)

此外,一些公共API决定提供中央/batch端点,例如google的gmail API

此外,如提及在restfulapi.net,也有资源“存储”,在其中存储和检索项目的整个列表一次通过PUT的概念-但是,这个概念并不服务器管理资源集合数:

商店是客户端管理的资源存储库。存储资源使API客户端可以放入资源,将其撤回并决定何时删除它们。商店永远不会生成新的URI。取而代之的是,每个存储的资源都有一个URI,该URI是客户端最初将其放入商店时选择的。


回答了您原来的问题后,这是尚未提及的另一种解决您问题的方法。请注意,这种方法有点不常规,看起来不像典型的REST API端点命名方案。我个人并没有遵循这种方法,但是我仍然认为应该考虑一下:)

这个想法是,您可以通过端点路径命名方案区分资源上的CRUD操作和其他与资源相关的操作(例如批处理操作)。

例如,考虑一个RESTful API,该API允许您在“公司”资源上执行CRUD操作,并且还希望执行一些与“公司”相关的操作,这些操作通常不适合与静态api关联的面向资源的CRUD方案。 –例如您提到的批处理操作。

现在,您无需区分资源/api/companies(例如/api/companies/22),而是可以区分以下两者:

  • /api/companies/items –即公司资源的集合
  • /api/companies/ops –即与公司资源有关的运营

对于items通常的RESTful API,将应用http-methods和resource-url naming-schemes(例如,如此此处所讨论的)

POST    /api/companies/items
GET     /api/companies/items
GET     /api/companies/items/{id}
DELETE  /api/companies/items/{id}
PUT     /api/companies/items/{id}
Run Code Online (Sandbox Code Playgroud)

现在,对于公司相关的操作,您可以/api/companies/ops/通过POST 使用路由前缀和呼叫操作。

POST    /api/companies/ops/batch-update
POST    /api/companies/ops/batch-delete
POST    /api/companies/ops/garbage-collect-old-companies
POST    /api/companies/ops/increase-some-timestamps-just-for-fun
POST    /api/companies/ops/perform-some-other-action-on-companies-collection
Run Code Online (Sandbox Code Playgroud)

由于POST请求不一定要创建资源,因此POST是在此处使用的正确方法:

POST方法执行的操作可能不会导致可以由URI标识的资源。 https://tools.ietf.org/html/rfc2616#section-9.5

  • 从美学的角度来看,我发现Google冒号惯例有些不为人所知。当发明一个新的动词时,更常见的是附加一个斜杠并向其添加内容-POST / api / items / batch-update 我将完全承认存在一个弊端,那就是现在您有一个保留字,如果需要子关联,则不能将其用于子关联,但我会权衡取舍以使用更干净的URL 。 (2认同)
  • @Quarkly REST 更像是一个“概念”而不是“标准”。它只对如何传输资源施加了很少的限制,并且没有详细规定如何设计 REST API,从而将如何处理事情留给了开发人员。由您的团队/公司定义您可以操作 REST API 的规则。有些设计指南是“好”的,有些是“坏”的,但是,说这是一个“糟糕的标准”并不能真正公正地对待 REST 作为一个概念/哲学,而且有点误导。 (2认同)