4

我一直在尝试构建一个基于超媒体的 API。事情似乎运作良好。说当我取/books/isbn/12313441213东西时,我得到了这样的东西:

<book>
  <id>123</id>
  <name>Hypermedia APIs</name>
  <description>Basic api design techniques</description>
  <tags>
    <tag>rest</tag>
    <tag>api</tag>
    <tag>service</tag>
  </tags>
  <authors>
    <link rel="author" uri="/authors/id/22" />
    <link rel="author" uri="/authors/id/18" />
  </authors>
</book>

现在我可以从这个资源中遍历作者。当我获取时,/books/by/author/id/18我得到这样的东西:

<books>
  <book id="123">
    <name>Hypermedia APIs</name>
    <link rel="self" uri="/books/id/123" />
  </book>
  <book id="191">
    <name>Chef Recipes for Rails Developers</name>
    <link rel="self" uri="/books/id/191" />
  </book>
  <book id="220">
    <name>Rails 4 Cookbook</name>
    <link rel="self" uri="/books/id/220" />
  </book>
  <book id="292">
    <name>Ruby 102</name>
    <link rel="self" uri="/books/id/292" />
  </book>
  <book id="432">
    <name>Semantic Architecture</name>
    <link rel="self" uri="/books/id/432" />
  </book>
  <book id="501">
    <name>Service Oriented Design</name>
    <link rel="self" uri="/books/id/501" />
  </book>
</books>

这对我来说似乎也很好。无论这种 uri 模板方式是否良好,我的问题是遍历这样的链接有多实用?

考虑到您想要完整的资源(包括作者详细信息),您必须至少对服务器进行 3 次调用。同样对于集合,您必须对服务器进行大量调用。是的,也许我可以在这里利用资源扩展,但是我为什么要使用超媒体链接,因为我所有的客户都会及时使用扩展资源。

我知道通过让客户端遍历链接,我们获得了很多收益(即,如果客户端构建基于关系的资源发现,当我们更改 api 时,它们受到的影响最小,或者它们被迫从资源端点本身获取最新的模式, ETC)。再说一次,这种方法的实用性或这种方法的性能会扼杀系统。

要么我在超媒体 api 设计中没有得到任何东西,要么超媒体 api 听起来不错,但似乎这只是一个理论上的想法,而不是实际的想法。

对此有什么想法吗?

4

2 回答 2

2

这一直是一个很好的问题。实际上,另一个大问题是:谁知道到达特定资源 R 的遍历 rel?

例如,要访问“book-detail”资源,客户端必须调用您的 api 条目,例如“/”,然后使用 rel“book-categories”获取 uri 到 book-categories,然后调用 OPTIONS查看是否可以在该资源上进行 GET 操作,然后获取书籍类别,然后将 rel 获取到“books-in-category”资源......等最终转到“book-detail”资源。到资源 R 的遍历路径应该是客户端知识的一部分。但不要对 url 进行硬编码,只需在运行时读取 url。这是考虑机器对人的场景。低效率仍然存在。在机器对机器的情况下,以“/”开头的自动机可以通过您的 API 并对您的资源进行某些处理。如果自动机必须访问树中的所有资源(或者可能是状态机),那么就没有效率低下。但是,如果自动机需要调用树中的资源,并且它只知道 API 的入口点,那么它将遇到多次调用以到达其点的问题。

许多人会告诉您使用 etags 和/或 memcached 引入缓存,但缓存是为了提高性能,您不能 100% 依赖缓存,因为缓存会过时,因此在这些情况下,用于遍历资源 R1 到 Rn 的代码应该在您的客户。

检查我的问题:https ://stackoverflow.com/questions/15214526/why-hypermedia-api

但是要回答您关于实用性的问题:如果您有一个业务工作流程,其中客户需要先访问资源 R1,然后是 R2,然后... Rn,并且您想强制执行该流程,那么超媒体是实用的。我假设没有通过 R1 -> R2 ->... Rx-1 直接调用 Resource Rx。

于 2013-08-15T00:04:20.237 回答
1

使用参数会更传统:

获取 /books?author=18

我希望响应看起来更像:

超媒体 API

您还可以使用参数来指示您希望子资源上的哪些字段可见。就像是

GET /books/18?expand=author(姓名,生日)

这将返回作者的姓名和生日作为响应中作者标签的一部分。然后,您可以为用户在索要书籍时获得多少作者信息(可能只是作者的自我和姓名)提供一个合理的默认值,但如果他们愿意,可以通过更改参数来获得更多详细信息。

这些类型的定制可以帮助减少需要拨打的电话数量。

另一个观察结果是,可以在客户端或中间代理上缓存大量此类数据。一本书或一位作者不太可能发生太大变化,因此这些资源可以让客户端缓存它们很长一段时间。然后根本没有往返 - 客户端访问他们自己的本地缓存以获取数据。

于 2013-08-08T00:10:32.593 回答