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

时间:2015-08-19 14:31:48

标签: json rest

一个简单的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]

在考虑White House Web StandardsWikipedia: REST Examples之后,现在使用以下示例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 Semantics POST阅读:

  

通过追加操作扩展数据库

PUT方法需要替换完整集合才能返回HTTP Semantics PUT引用的等效表示:

  

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

[UPDATE2]

对于多个对象的更新方面似乎更加一致的替代方案似乎是PATCH方法。 PUT和PATCH之间的区别在Draft 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有效内容
  • 的描述创建或更新一个或多个项目

3 个答案:

答案 0 :(得分:36)

您可以修补该集合,例如

SortedList

技术上,PATCH会识别URL中的记录(即PATCH SortedDictionary而不是请求正文中的记录,但这似乎是一个很好的实用解决方案。

为了支持在单个调用中删除,创建和更新,标准REST约定并不真正支持。一种可能性是一种特殊的“批处理”服务,可以让你一起组装电话:

PATCH /items
[ { id: 1, name: 'foo' }, { id: 2, name: 'bar' } ]

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

/items/1

不是很标准,但我已经完成了它并且有效。

答案 1 :(得分:5)

  

通过一个请求更新多个资源-是标准操作还是应避免?

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

  

这是标准的吗?

目前尚无公认的REST API标准,因此这个问题很难回答。但是,通过查看一些普遍引用的api设计指南,例如jsonapi.orgrestfulapi.netmicrosoft api design guideIBM's REST API Conventions,它们都没有提到批处理操作,您可以推断出操作通常不被理解为REST API的标准功能。

也就是说,Google API设计指南是个例外,该指南mentions创建“自定义”方法,这些方法可以使用冒号(例如,冒号)通过资源进行关联。 https://service.name/v1/some/resource/name:customVerb,它也明确提到了批处理操作作为用例:

  

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

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

POST /api/items:batchUpdate

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

此外,就像restfulapi.net上的mentioned一样,还有资源“存储”的概念,您可以在其中通过PUT一次存储和检索项目的整个列表–但是,此概念不算在内对于服务器管理的资源集合:

  

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


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

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

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

现在,您无需在/api/companies(例如/api/companies/22)下面直接显示资源,就可以区分:

  • /api/companies/items –即公司资源的集合
  • /api/companies/ops –与公司资源相关的操作

对于items,通常使用RESTful api http方法和资源URL命名方案(例如,如herehere所述)

POST    /api/companies/items
GET     /api/companies/items
GET     /api/companies/items/{id}
DELETE  /api/companies/items/{id}
PUT     /api/companies/items/{id}

现在,对于与公司相关的操作,您可以使用/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

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

  

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

答案 2 :(得分:1)

据我了解REST概念,它涵盖了一个请求更新多个资源。实际上,这里的技巧是假设围绕这些多个资源的容器并将其作为单个资源。例如。您可以假设ID列表标识包含多个其他资源的资源。

在那些examples in Wikipedia中,他们还谈到了Plural中的资源。