超媒体API链接遍历&;实用性

超媒体API链接遍历&;实用性,api,rest,service,hypermedia,Api,Rest,Service,Hypermedia,我一直在尝试构建一个基于超媒体的API。事情似乎进展顺利。比如说,当我取回/books/isbn/12313441213时,我会得到这样的东西: <book> <id>123</id> <name>Hypermedia APIs</name> <description>Basic api design techniques</description> <tags> <ta

我一直在尝试构建一个基于超媒体的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>
  <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时,他们将受到最小的影响,或者他们被迫从资源端点本身获取最新的模式,等等)。再说一次,这种方法的实用性,或者说这种方法的性能会毁掉这个系统

要么我在超媒体api设计方面没有什么收获,要么超媒体api听起来很棒,但它似乎只是一个理论上的想法,而不是一个实际的想法


对此有何想法?

使用参数更为传统:

获取/获取书籍?作者=18

我希望得到的答复更像是:

超媒体API

您还可以使用参数指示子资源上要显示的字段。差不多

GET/books/18?expand=作者(姓名、生日)

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

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


另一个观察结果是,可以在客户端或中间代理上缓存大量数据。对于一本书或一位作者来说,不太可能有太大的改变,因此这些资源可以让客户端长期缓存它们。然后根本就没有往返-客户端点击自己的本地缓存获取数据。

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

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

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

检查我的问题:


但要回答您关于实用性的问题:如果您有一个业务工作流,其中客户机需要转到资源R1,那么R2,然后。。。如果你想加强这种流动,超媒体是实用的。我假设没有通过R1->R2->直接调用资源Rx。。。Rx-1.

谢谢你的回答,Eric。URI模板化问题是一个有争议的话题。我认为这两种情况都是有效的,这取决于您希望在您的服务之上构建什么样的功能。在你提到资源扩张的部分,我仍然很困惑为什么会有人在这种情况下使用超媒体链接。我非常肯定虚拟客户很快就会采用完全扩展的资源。只有有意识的客户才会明智地使用API。考虑到模式更新等因素,缓存也可能是一种惩罚。但我认为一定有更好的方法或表示方式。。您不认为吗?启用私有缓存并在api的根资源上设置最大年限足以消除大量冗余调用。ETag和memcached不是必需的。链接提示可用于防止选项往返的需要。客户机也没有理由不选择保留书签以备将来使用,只要它能够处理书签在以后某个时候失效的后果。@Darreller它不仅仅是api的根资源,它完全取决于资源序列的深度。在现实中,资源被构造成一个状态机,但为了简单起见,我想把它看作一棵树。因此,您应该考虑从根资源到叶资源的所有资源,并查看缓存是否合适;不仅仅是根资源必须是高效的。请记住,在超媒体中,根资源不一定提供所有资源URL,它只提供从根可以访问的内容。同意根不是唯一需要缓存以优化效率的资源。然而,理想情况下,根到叶的遍历应该