REST复杂/复合/嵌套资源[关闭]


177

我正在努力解决在基于REST的API中解决概念的最佳方法。不包含其他资源的固定资源没有问题。我遇到麻烦的地方是复杂的资源。

例如,我有一部漫画资源。ComicBook拥有所有喜欢各种各样它的属性authorissue numberdate,等。

一本漫画书也有1..n封面清单。这些封面是复杂的对象。它们包含有关封面的许多信息:艺术家,日期,甚至是封面的base 64编码图像。

对于GET上,ComicBook我可以退回漫画,以及所有的封面,包括其base64版本的图像。获得一部漫画可能不是什么大事。但是,假设我正在构建一个客户端应用程序,该应用程序希望在表格中列出系统中的所有漫画。
该表将包含ComicBook资源中的一些属性,但是我们当然不想显示该表中的所有封面。归还1000本漫画书,每本漫画书都有多个封面,这将导致大量数据荒谬地通过网络传播,在这种情况下,最终用户不需要这些数据。

我的本能是制造Cover资源并ComicBook包含掩护。所以现在Cover是一个URI。GET现在在漫画书上工作时,Cover我们会为每个封面发送一个URI ,而不是大量的资源,客户可以根据需要检索Cover资源。

现在,我在创建新漫画时遇到了问题。当然Comic,在创建时,我肯定会想要创建至少一个封面,实际上这可能是一条业务规则。
所以现在我卡住了,我要么强制客户端通过先提交给执行业务规则Cover,获得URI为盖,然后POST荷兰国际集团一个ComicBook与URI列表,或者我POSTComicBook发生在不同的资源寻找比它吐出出来。对于收到的资源POSTGET深拷贝,其中传出GET小号包含对相关资源的引用。

Cover资源在任何情况下都可能是必需的,因为在某些情况下,我确定作为客户端我想解决的问题涵盖了方向。因此,无论依赖资源的大小如何,问题都以一般形式存在。通常,您如何处理复杂的资源而又不强迫客户端仅“知道”这些资源的组成方式?



1
我正在尝试坚持使用HATEAOS,在我看来,这与使用类似的东西背道而驰,但我来看看。
jgerman 2011年

本着不同的精神。但是,所有权与您建议的解决方案(问题中的解决方案)不同。stackoverflow.com/questions/20951419/...
韦斯

Answers:


64

@ray,精彩的讨论

@jgerman,不要忘了仅仅因为它是REST,并不意味着必须从POST中固定资源。

您选择包含在资源的任何给定表示形式中的内容取决于您。

您单独引用封面的情况仅仅是创建父资源(漫画书),而其子资源(封面)可能会被交叉引用。例如,您可能还希望单独提供对作者,发布者,字符或类别的引用。您可能希望单独创建这些资源,也可以在将它们作为子资源引用的漫画书之前创建。或者,您可能希望在创建父资源时创建新的子资源。

封面的具体情况稍微复杂一点,因为封面确实确实需要一本漫画书,反之亦然。

但是,如果您将电子邮件视为资源,而将发件人地址视为子资源,则显然仍可以单独引用发件人地址。例如,从地址获取全部。或者,使用先前的发件人地址创建一条新消息。如果电子邮件是REST,您可以轻松地看到许多交叉引用的资源可用:/ received-messages,/ draft-messages,/ from-addresses,/ to-addresss,/ addresses,/ subjects,/ attachments,/ folders ,/ tags,/ categories,/ labels等。

本教程提供了一个很好的交叉引用资源示例。 http://www.peej.co.uk/articles/restfully-delicious.html

这是自动生成数据的最常见模式。例如,您不会为新资源发布URI,ID或创建日期,因为它们是由服务器生成的。但是,当您取回新资源时,您可以检索URI,ID或创建日期。

关于二进制数据的示例。例如,您要发布二进制数据作为子资源。当您获得父资源时,您可以将那些子资源表示为相同的二进制数据,也可以表示为表示二进制数据的URI。

表单和参数已经不同于资源的HTML表示形式。张贴二进制/文件参数以生成URL并不是一个麻烦。

当您获取新资源的表单(/ comic-books / new)或获取表单以编辑资源(/ comic-books / 0 / edit)时,您正在要求该资源的表单特定表示。如果使用内容类型“应用程序/ x-www-form-urlencoded”或“ multipart / form-data”将其发布到资源集合,则要求服务器保存该类型表示形式。服务器可以响应已保存的HTML表示形式或其他形式。

您可能还希望出于API或类似目的,将HTML,XML或JSON表示形式发布到资源集合中。

考虑到漫画后张贴的封面,但也要求漫画具有封面,也可以按照您的描述来表示您的资源和工作流程。示例如下。

  • 允许延迟创建封面
  • 允许创建具有所需封面的漫画书
  • 允许交叉引用封面
  • 允许多个封面
  • 创建漫画书草案
  • 创建漫画封面
  • 出版漫画书草案

GET / comic-books
=> 200 OK,获取所有漫画书。

GET / comic-books / 0
=> 200 OK,获取带有封面(/ covers / 1,/ covers / 2)的漫画书(id:0)。

GET / comic-books / 0 / covers
=> 200 OK,获取漫画封面(id:0)。

GET / covers
=> 200 OK,获取所有封面。

GET / covers / 1
=> 200 OK,用漫画书(/ comic-books / 0)获取封面(id:1)。

GET / comic-books / new
=> 200 OK,获取表格以创建漫画书(表格:POST / draft-comic-books)。

POST / draft-comic-books
title = foo
author = boo
Publisher = goo
Published = 2011-01-01
=> 302找到,位置:/ draft-comic-books / 3,重定向到草稿漫画书(id:3),封面(二进制)。

GET / draft-comic-books / 3
=> 200 OK,获得带有封面的漫画草稿(id:3)。

GET / draft-comic-books / 3 / covers
=> 200 OK,获取漫画草案的封面(/ draft-comic-book / 3)。

GET / draft-comic-books / 3 / covers / new
=> 200 OK,获取表格以创建漫画草案的封面(/ draft-comic-book / 3)(表格:POST / draft-comic-books / 3 /盖子)。

POST / draft-comic-books / 3 / covers
cover_type = front
cover_data =(binary)
=> 302找到,位置:/ draft-comic-books / 3 / covers,重定向到漫画书草案的新封面(/ draft-comic -book / 3 / covers / 1)。

GET / draft-comic-books / 3 / publish
=> 200 OK,获取表格以发布漫画草案(id:3)(表格:POST / published-comic-books)。

POST / published-comic-books
标题= foo
作者= boo
出版商= goo
发布= 2011-01-01
cover_type = front
cover_data =(binary)
=> 302找到,位置:/ comic-books / 3,重定向到已出版的漫画书(编号:3)带盖。


我是这个的新手,想赶紧学习。我发现这非常有帮助。但是,在我今天阅读的其他博客等文章中,使用GET来执行操作(尤其是不等幂的操作)的做法会被反对。所以它不应该是POST / draft-comic-books / 3 / publish吗?
加里·麦吉尔

3
@GaryMcGill在他的示例中,/ draft-comic-books / 3 / publish仅返回HTML表单(不修改任何数据)。
Olivier Lalonde

@Olivier是正确的。“发布”一词在那里表示表单的功能。但是,由于您希望将动词限制在HTTP方法中,因此应该将其发布到已出版漫画的资源中。...如果这是一个网站,则可能需要一个URI才能使表单发布内容。...尽管,如果发布动作仅仅是漫画页面上的一个按钮,则该单按钮形式可以直接发布到/ published-comic-books URI。
亚历克斯

@Alex,在POST请求中,我将返回201 Created,将新资源的URL作为响应头中的Location。
ismriv

2
@Stephane,重定向只会使控制器的一切变得更简单。即使对于API,让create控制器返回新内容的位置,然后让show控制器处理新内容的显示也更简单。虽然,对于API客户端来说,获取内容而不用担心重定向会更好/更简单。
2014年
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.