RESTful API:更新实体产生副作用时返回的内容

Posted

技术标签:

【中文标题】RESTful API:更新实体产生副作用时返回的内容【英文标题】:RESTful APIs: what to return when updating an entity produces side-effects 【发布时间】:2015-05-27 09:54:56 【问题描述】:

我们的一个 API 有一个 tasks 资源。 API 的使用者可以根据需要创建、删除和更新给定的任务。

如果任务完成(即,其状态通过PUT /tasks/<id> 更改),结果可能会自动创建一个新任务

我们正在努力使其保持 RESTful。告诉调用用户新任务已创建的正确方法是什么?我想到了以下解决方案,但我认为它们都有缺点:

    PUT 响应中添加一个附加字段,其中包含有关最终新任务的信息。 仅返回更新的任务,并期望用户调用GET /tasks 以检查是否已创建任何新任务。

在我看来,选项 1 打破了 RESTful-ness,因为 API 预计只会返回有关更新实体的信息。选项 2 期望用户做一些事情,但如果他不这样做,那么没有人会意识到创建了一个新任务。

谢谢。

更新:PUT 调用返回一个 HTTP 200 代码以及更新任务的完整 JSON 表示。

@tophallen 建议有一个任务树,以便(如果我没记错的话)选项 2 中返回的实体包含作为直接子项的新任务。

【问题讨论】:

您可以尝试在响应中添加一个新标头,例如标识新任务的 X-New-Task。 我假设在案例 2 中您返回 202 的?是否考虑过任务树? - 我认为一个任务作为另一个任务的直接结果会被认为与更新的实体有关,因此作为结果的属性是相关的。 @tophallen 我们在更新后返回纯 200 和实体的完整 JSON 表示(我们遵循对整个 RESTful 范式的这种解释:***.com/a/798174/624356)。任务树也可以是一个选项,但我想避免仅仅为了解决这个问题而使用树结构(尽管如果没有找到其他替代方案,我们可能会选择它)。 @cyber_rookie 这算是一个好习惯吗? 这似乎不是一个坏主意,但考虑到您想要实现的目标,这似乎是一个选择,尽管它可能存在一些瓶颈,例如一些重写 HTTP 的防火墙标题。 【参考方案1】:

您确实有 2 个选项和 200 状态 PUT,您可以制作标题(如果您这样做,请查看 this 帖子)。当然不是一个糟糕的选择,但您需要确保它在整个站点范围内被规范化,有据可查,并且您没有任何东西,例如防火墙/F5/等/重写您的标头。

不过,这样的选择会是一个公平的选择:

HTTP/1.1 200 OK
Related-Tasks: /tasks/11;/tasks/12

 ...task response... 

或者您必须在响应正文中向客户端提供一些指示。您可以有一个支持子任务的任务结构,或者您可以规范化所有响应以包含“元”内容的空间,即

HTTP/1.1 200 OK

    "data":  ...the task ,
    "related_tasks": [],
    "aggregate_status": "PartiallyComplete"

这样的东西到处都使用(有点工作,因为听起来你不只是开始这个​​项目)可能非常有用,因为你也可以将它用于分页等场景。

就我个人而言,我认为如果您让related_tasks 属性仅包含调用子任务的路由或要调用的 ID,这可能是最好的、更轻松的响应,因为客户端可能并不总是关心调用检查无论如何,立即执行所述子任务。

编辑: 实际上,我想得越多-在您的情况下,标题就越有意义-因为客户端可以在任务处理过程中的任何时候更新任务,可能有也可能没有子任务在玩-所以修改数据当子任务开始时客户端调用更新任务的机会的结构似乎比收益更多。标题将允许您轻松添加子任务并在 any 点通知用户 - 您可以将相同的内容应用于恰好立即完成并启动子任务的任务的 POST,等等。它可以轻松支持多个任务。我认为这也让它保持最安静并减少服务器调用,客户端总是能够知道进程链中发生了什么。标头的详细信息可以定义,但我认为在这种情况下,让它指向资源而不是 资源中的键更为传统。

如果还有其他选择,我很想听听。

【讨论】:

添加标题似乎是双赢的。 +1 是的,它看起来是最合理的选择。谢谢你们,tophallen 和@cyber_rookie。【参考方案2】:

看起来您非常关心 RESTful,但您没有使用 HATEOAS,这是矛盾的。如果您使用 HATEOAS,则相关实体只是另一个链接,客户可以随心所欲地关注它们。您所拥有的在 REST 中是没有问题的。如果这对您来说听起来很新鲜,请阅读以下内容:http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven

在我看来,选项 1 打破了 RESTful-ness,因为 API 是 预计仅返回有关更新实体的信息。

这不是真的。 API 应返回任何记录为该媒体类型可用信息的信息。如果您记录了一项任务具有相关副作用任务的字段,那么它没有任何问题。

【讨论】:

以上是关于RESTful API:更新实体产生副作用时返回的内容的主要内容,如果未能解决你的问题,请参考以下文章

使用 RESTful API 时更新 UI

我的RESTful API没有更新数据库,但是ajax返回成功

细说Restful API之幂等性

通过 RESTful API 查询 SPARK 作业产生的数据

具有两个独立主键的实体的 RESTful API 行为

SpringMVC_[5]使用RESTful风格的更新和删除遇到的问题