当我尝试实施REST时,与REST相关的几个概念就在我的脑海中。
我有一个包含业务逻辑的REST-ful后端API系统,以及一个提供UI的Web应用程序。从有关REST的各种资源(特别是REST在实践中:超媒体和系统体系结构)中,我知道我不应该公开实体的原始标识符,而应该返回带有的超链接rel="self"
。
考虑这个例子。REST api具有返回一个人的资源:
<Person>
<Links>
<Link rel="self" href="http://my.rest.api/api/person/1234"/>
</Links>
<Pets>
<Link rel="pet" href="http://my.rest.api/api/pet/678"/>
</Pets>
</Person>
Web应用程序出现问题。假设它返回的页面包含浏览器的超链接:
<body class="person">
<p>
<a href="http://my.web.app/pet/???????" />
</p>
</body>
我应该在href
属性中添加什么?当用户打开目标页面时,如何将API实体URL保留在Web应用程序中以便能够获取该实体?
要求似乎有冲突:
- 超链接
href
应指向Web应用程序,因为它是承载UI的系统 - 本
href
应该有实体的一些ID,因为Web应用程序必须能够在目标页打开时,解决实体 - 提到的书说,Web应用程序不应解析/构造REST URL,因为它不是基于REST的。
URI对消费者应该是不透明的。只有URI的颁发者知道如何解释它并将其映射到资源。
因此,我不能仅仅1234
取自API响应URL,因为作为RESTful客户端,我应该将其视为http://my.rest.api/api/AGRIDd~ryPQZ^$RjEL0j
。另一方面,我必须提供一些URL,这些URL可以引到我的Web应用程序,并且足以使该应用程序以某种方式还原API的原始URL,并使用该URL来访问API资源。
最简单的方法可能只是使用资源的API URL作为它们的字符串标识符。但是网页网址http://my.web.app/person/http%3A%2F%2Fmy.rest.api%2Fapi%2Fperson%2F1234
很丑陋。
对于台式机应用程序或单页javascript应用程序而言,这似乎非常容易。由于它们持续存在,因此它们可以将URL与服务对象一起保留在内存中,以延长应用程序的生命周期,并在必要时使用它们。
使用Web应用程序,我可以想象几种方法,但是所有方法似乎都很奇怪:
- 替换API URL中的主机,并仅保留结果。巨大的缺点是,它需要Web应用程序处理API生成的任何URL,这意味着怪异的耦合。而且,它不再是RESTful的,因为我的Web应用程序开始解释URL。
- 公开REST API中的原始ID及其链接,使用它们来构建Web App的URL,然后使用Web App Server上的ID在API中找到所需的资源。这样比较好,但是会影响Web应用程序服务器的性能,因为Web应用程序必须通过REST服务导航来发出一系列形式的获取ID请求的链接,以处理来自浏览器的任何请求。对于有些嵌套的资源,这可能会很昂贵。
self
将api返回的所有URL 存储在Web应用服务器上的持久(DB?)映射中。为它们生成一些ID,使用这些ID构建Web应用程序页面URL并获取REST服务资源的URL。也就是说,我http://my.rest.api/pet/678
用一个新的密钥将URL 保留在某处3
,然后将网页URL生成为http://my.web.app/pet/3
。这看起来像某种HTTP Cache实现。我不知道为什么,但是对我来说似乎很奇怪。
还是所有这些都意味着RESTful API不能用作Web应用程序的后端?