REST - 使用单个 POST 创建嵌套资源

Posted

技术标签:

【中文标题】REST - 使用单个 POST 创建嵌套资源【英文标题】:REST - Creating Nested Resources with single POST 【发布时间】:2013-01-11 09:37:13 【问题描述】:

以 RESTful 的方式思考,使用 POST 在一次调用中创建资源及其子资源是否正确? 在我的应用程序中,我有资源/notices/notice 和子资源/notices/notice/photos/photophoto 不能没有 notice,但 notice 不一定有照片。通常,我必须先做一个 POST 来创建通知,然后再做一个 POST 来添加照片。

现在我想允许创建直接附有照片的通知,通过对 /notices/notice/photos/photo 的单个 POST 请求来创建 /notices/notice/notices/notice/photos/photo,使用描述两种资源的多部分内容(通知的 JSON,照片的二进制)。我想我只会为子资源返回 Location 标头。

本质上,我希望这可以防止 android 客户端向服务器发送两个 POST 请求以上传带有照片的通知。 它是否正确?还是违反了 REST 原则?我应该考虑将它们分开并提出两个不同的请求吗?还是将照片视为与通知不同的实体是错误的?我应该只保留/notices/notice 作为资源,使用 PUT 添加照片吗?

哪个是最好的解决方案?

【问题讨论】:

【参考方案1】:

是的,在创建父资源的同时创建子资源并没有错。甚至可以使用 PUT 而不是 POST 来执行此操作,因为父 URL 下的所有内容都属于/属于您正在上传的资源。

编辑:

现在我想允许创建直接附有照片的通知,通过向/notices/notice/photos/photo 发送一个POST 请求来创建/notices/notice/notices/notice/photos/photo

这点我不同意。我建议发布到集合资源的 URL /notices。您将通知及其照片作为单一表示(请求正文)提供。然后,后端将为通知和任何组成照片创建资源。

【讨论】:

当然按照这个逻辑,端点之后的一切都是对根资源的修改,因此使POST 的想法变得多余? (我可能误会了你?) 理论上是的。您可以将 /questions 视为 ***.com 的子资源。然而,这并不会使 POST 变得多余。 我认为使用 POST 将是这里唯一明智的选择,因为 OP 没有(直接)修改最顶层的资源?使用PUT 创建资源是否意味着该子资源已经存在? 我不这么认为。想想一个资源有多个字段的 API,其中一个是大数据 blob。可能是某些客户端不想要这个,所以 API 作者创建了 3 个 URI:/resource/resource?blob=false/resource/blob 来发送整个资源、没有大数据项的资源和数据独自的。在这种情况下,包含所有资源的 /resource 的 PUT 也会使其他两个 URI 失效(条件 GET/HEAD 不会返回 304)。 @James:似乎还没有 REST 聊天室,所以我创建了一个:chat.***.com/rooms/22578/restful-chat 加入我们可以讨论。我对你的意见很感兴趣。【参考方案2】:

尽管在许多情况下它是必不可少的,但 RESTful 架构风格并未正式解决多次编辑/创建问题。

当您需要报告部分集合的故障时,问题就开始了,当故障有不同的原因时,问题会变得更糟。

它将影响选择正确的超媒体控件,这对于客户在给定的事务/对话中找到前进的方式至关重要。

所以我的建议是使用嵌套循环或 POST 请求,而不是使用 POST 来创建嵌套 Resources ,以便更轻松、更清晰地处理每个 Resource 状态更改。

【讨论】:

解决方案是在第一个错误时失败并回滚服务器状态。以这种方式实现事务是否值得努力取决于您的服务器有多忙。 请到chat.***.com/rooms/22578/restful-chat 讨论这个问题。我想听听更多关于你要说的话。

以上是关于REST - 使用单个 POST 创建嵌套资源的主要内容,如果未能解决你的问题,请参考以下文章

创建 REST API 时使用 Laravel 嵌套动态资源控制器的正确方法

django rest 框架 POST 请求因嵌套序列化而失败

S3 REST API 和 POST 方法

用于创建资源的 REST API 补丁方法

REST API - 在单个请求中批量创建或更新 [关闭]

Flowable入门系列文章91 - 一般可流动的REST原则 02