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

9
以RESTful的方式思考,使用POST在一个调用中创建一个资源及其子资源是正确的吗?在我的应用程序中,我有资源/notices/{notice}和子资源/notices/{notice}/photos/{photo}。没有{notice},就不可能存在{photo},但一个{notice}并不一定有照片。通常,我需要先进行一个POST创建一个notice,然后再进行另一个POST添加照片。
现在,我想允许直接附加照片创建通知,通过启用对/notices/{notice}/photos/{photo}的单个POST请求来创建/notices/{notice}和/notices/{notice}/photos/{photo},其中包含描述两个资源的多部分内容(notice的JSON,照片的二进制)。我认为只为子资源返回Location头。
本质上,我想要这样做是为了防止Android客户端向服务器发送两个POST请求以上传带有照片的通知。这样做是否正确?还是侵犯了REST原则?我应该考虑保持它们分开并进行两个不同的请求吗?或者将照片视为与通知不同的实体是错误的吗?我应该只保留/notices/{notice}作为资源,使用PUT添加照片吗?
哪种方案最好?
2个回答

5
是的,在创建父级资源的同时创建子资源没有问题。你甚至可以使用PUT而不是POST来完成这个操作,因为在父URL下的所有内容都是上传的资源的一部分/属于资源。

编辑:

现在我想直接附加照片创建通知,通过单个POST请求到/notices/{notice}/photos/{photo}实现/notices/{notice}/notices/{notice}/photos/{photo}的创建。

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


按照这个逻辑,端点之后的所有内容都是根资源的修改,因此使“POST”的概念变得多余了?(也许我误解了你的意思?) - James
理论上是可以的。你可以把/questions看作是stackoverflow.com的子资源。但这并不意味着POST方法变得多余。 - Nicholas Shanks
我认为在这种情况下使用POST是唯一明智的选择,因为OP没有直接修改最顶层资源。如果使用PUT创建资源,则意味着该子资源已经存在? - James
我不这么认为。想象一下一个API,其中一个资源有几个字段,其中一个是大数据块。有些客户可能不需要它,因此API作者创建了3个URI:/resource/resource?blob=false/resource/blob以发送整个资源、没有大数据项的资源和仅数据。在这种情况下,PUT到包含所有资源的/resource也会使其他两个URI过时(条件GET/HEAD将不返回304)。 - Nicholas Shanks
@James:似乎还没有一个关于REST的聊天室,所以我创建了一个:http://chat.stackoverflow.com/rooms/22578/restful-chat。欢迎加入讨论,我很想听听你的意见。 - Nicholas Shanks
客户端在失败的情况下如何处理?或者服务器将如何通知个别HTTP响应代码或资源状态? - TheWhiteRabbit

1

虽然在许多情况下它是必要的,但RESTful架构风格并没有正式解决多次编辑/创建的问题。

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

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

因此,我的建议是使用嵌套循环或POST请求而不是单个POST来创建嵌套资源,以便更容易和清晰地处理每个资源状态的更改。


解决方法是在第一个错误发生时失败并回滚服务器状态。是否值得以这种方式实现事务取决于您的服务器有多忙。 - Nicholas Shanks
请加入 http://chat.stackoverflow.com/rooms/22578/restful-chat 进行讨论。我想听听您的更多意见。 - Nicholas Shanks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接