RESTful在一个请求中创建多个项目的方式


122

我正在开发一个小型客户端服务器程序来收集订单。我想以“ REST(有效)方式”执行此操作。

我想做的是:

收集所有订单行(产品和数量)并将完整的订单发送到服务器

目前,我看到执行此操作的两个选项:

  1. 将每个订单行发送到服务器:POST数量和product_id

我实际上不想这样做,因为我想限制对服务器的请求数,因此选项2:

  1. 收集所有订单行并将它们立即发送到服务器。

我应该如何实施选项2?我有两个想法:将所有订单行包装在JSON对象中,然后将其发送到服务器或使用数组发布订单行。

实施选项2是个好主意还是好的做法,如果是的话,我应该怎么做。

什么是好习惯?

rest  post 

Answers:


74

我相信解决此问题的另一种正确方法是创建另一个资源,该资源代表您的资源集合。例如,假设我们有一个类似的端点/api/sheep/{id},并且可以通过POST /api/sheep创建一个羊资源。

现在,如果我们要支持批量创建,则应该考虑使用新的羊群资源/api/flock(或者/api/<your-resource>-collection如果您缺少更好的有意义的名称)。请记住,资源不需要映射到您的数据库或应用程序模型。这是一个普遍的误解。

资源是更高级别的表示,与您的数据无关。对资源进行操作会产生严重的副作用,例如向用户发出警报,更新其他相关数据,启动寿命长的进程等。例如,我们可以将文件系统甚至unix ps命令映射为REST API。

我认为可以安全地假设运行资源也可能意味着要创建其他几个实体。


我同意这一点。您应该抽象出资源集合的概念,并将其视为资源。这会给你更多的灵活性,在未来为好,当你要开始进行这项工作等,做业务
villy393

这是正确的方法。这不会破坏POST收集请求。由于,它用于过帐单个实体。用“单独的批量实体”发送批量请求是正确的方法。
Sorter

2
我喜欢您api端点这么多地用羊和羊命名!从某种程度上讲,它几乎符合圣经的含义:“我还有其他的羊,它们不属于这种羊群;我也必须把它们放在一起,它们才能听到我的声音;它们将与一只牧羊犬成群。” 约翰福音10:16
Evgeny

1
有趣的是,当您要创建单个资源时,人们建议在URL中使用(集合的)复数形式,例如:将POST发送到/ api / books以创建一本书。但是,当您要创建100本书(在单个请求中为json)时,会将100本书的集合发布到哪个URL?那就是不安的开始。
code4kix

@ code4kix你可以使用/api/book-group/api/book-collection或者类似的东西。
miguelcobain

46

尽管在许多系统中批量操作(例如批创建)是必不可少的,但是RESTful体系结构样式并未正式解决它们。

我发现按照您的建议发布集合基本上可以正常工作,但是当您需要响应此类请求报告失败时会出现问题。当由于不同原因而导致多次失败或服务器不支持事务时,此类问题会更​​加严重。我的建议是,如果没有性能问题,例如当服务提供商位于LAN(而非WAN)上或数据相对较小时,向服务器发送100个POST请求是值得的。保持简单,从单独的请求开始,如果您遇到性能问题,请尝试进行优化。


3
您是否找到了针对批处理中的错误的解决方案?在移动连接上发送100个帖子请求以显示页面接缝,这是一个坏主意。
托马斯·阿勒

我将错误附加到数组,将用户路由到419冲突错误页面(并将该错误返回给客户端),并显示错误数组。请参阅下面的详细信息。
Eric Fuller 2013年

5
这是无稽之谈。问题是关于发送许多物品的订单,正如许多人所说,您只能在一个POST请求的实体中发送订单。服务器如何处理这完全是另一回事。在这种情况下,我认为创建订单,填充该订单的内容以及填充无法执行的细节都没有问题。这样,用户便可以看到他们的订单,并看到除了N个商品外,所有商品都已添加到该订单中,但是有些商品缺货,或者系统不知道如何处理。另一个更简单但不太用户友好的选项是拒绝所有内容
thecoshman 2014年

2
@thecoshman在3.25年内发生了很大变化。您可能应该发布问题的完整公式化答案。
dlamblin 2014年

3
@dlamblin是的,我可能应该做很多事情...也许在某个阶段就可以解决...
thecoshman 2014年

9

Facebook解释了如何执行此操作:https : //developers.facebook.com/docs/graph-api/making-multiple-requests

简单的批处理请求

批处理API接收一个表示为JSON数组的逻辑HTTP请求的数组-每个请求都有一个方法(对应于HTTP方法GET / PUT / POST / DELETE等),relative_url(在graph.facebook之后的URL部分)。 com),可选的标头数组(对应于HTTP标头)和可选的正文(用于POST和PUT请求)。Batch API返回表示为JSON数组的逻辑HTTP响应数组-每个响应都有一个状态码,一个可选的标头数组和一个可选的主体(这是JSON编码的字符串)。


1
这是一个非常有趣的链接,建议的解决方案对我来说似乎可用。无论如何,在StackOverflow上,首选的答案是在答案的主体中解释解决方案的概念,因为链接可能会更改或消失。
Jan Vlcinsky '16

7
那确实是Facebook的方式,不一定是OP所要求的RESTful
0cd

我认为将多个无关请求组合在一起时,批处理API(来自Google,Facebook等-@PuneetArora)更加有用。创建一个创建一个项目的请求,然后将所有这些请求组合在一起以发送一个项目集合是“精神错乱”(Einstein)。只需创建一个传递项目集合的请求即可。
tfmontague '17

8

您的想法对我来说似乎是正确的。具体实施取决于您的偏好。您可以为此使用JSON或仅使用参数(“ order_lines []”数组),然后执行

POST /orders

由于您将要在一个操作(订单及其行)中一次创建更多资源,因此至关重要的是验证每个资源并仅在所有资源都通过验证后才保存它们,即。您应该在交易中进行。



5

实际上,我最近一直在为此努力,这就是我正在努力的方向。

如果添加多个资源的POST成功,则返回200 OK(我正在考虑使用201,但是用户最终不会落在已创建的资源上)以及显示已添加的所有资源的页面,无论是已读还是已读-或可编辑的方式。例如,用户能够使用仅包含一个文件输入的表单选择多个图像并将其发布到画廊。如果POST请求完全成功,则会为用户显示一组针对创建的每个图像资源表示形式的表单,这些表单使他们可以指定有关每个表单的更多详细信息(名称,描述等)。

如果无法创建一个或多个资源,则POST处理程序将中止所有处理,并将每个错误消息附加到数组中。然后,返回419冲突,并将用户路由到419冲突错误页面,该页面显示错误数组的内容以及返回提交表单的方式。


-2

您将不希望发送100个订单行的HTTP标头。您都不希望生成超出必要数量的请求。

将整个订单以一个JSON对象的形式发送到服务器:服务器/订单或服务器/订单/新。返回指向的内容:server / order / order_id

还可以考虑使用CREATE PUT而不是POST


我想他提到了HTTP POST方法。没有CREATE HTTP方法。
米兰诺沃塔09年

不在吗 哦,等等,没有。取而代之的是PUT。
令人愉快的2009年

22
您到底为什么要使用PUT创建内容?这正是HTTP POST方法的用途。
thecoshman 2013年

8
当您希望客户端指定资源的URI时(例如在webdav中),可以使用PUT创建资源。我不同意张贴者对PUT的使用,但是它确实在创建资源方面占有一席之地,尽管该范围可能受到限制。
user602525 2015年

2
注意:POST实体应导致该实体成为请求中寻址的资源的从属,并且不是幂等的。PUT替换地址处的实体,并且是幂等的。幂等性(单词?)是消费者的重要期望。
路加·普普利特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.