为 RESTful(超媒体)API 编写客户端

Posted

技术标签:

【中文标题】为 RESTful(超媒体)API 编写客户端【英文标题】:Writing a client for a RESTful (hypermedia) API 【发布时间】:2012-03-26 22:10:17 【问题描述】:

这几天我一直在阅读“真正的”RESTful API,我认为我已经接近于摸索它的内容了。

但我偶然发现的一件事是,我什至无法想象如何为“真正的”超媒体 API 编写客户端:

    我读过的大多数示例都是关于浏览器和蜘蛛的,但这并不是特别有用:一个是人为导向的“智能”,另一个是愚蠢和“随机”的。就目前而言,我的印象是,您需要学习 AI 才能让客户正常工作。

    我不清楚的一点是客户端如何知道在任何给定链接上使用哪个动词?这是否隐含在 uri 的“rel”类型中?另一种选择(阅读 here)似乎是使用 xhtml 并拥有一个可以解析和发布表单的客户端。

    链接更改的可能性有多大,但链接的路径不会更改? 在您看到的大多数示例中,路线和链接是相同的:

例如。如果我想设置一个客户端,它将把我从 Toni's Cake Shop 带回的蛋糕列表:

http://tonis.com
 link:  type : "cakes" ; uri : "http://tonis.com/cakes"  

当 Toni's 变成 Toni's Food Shop 并且链接变为 http://tonis.com/desserts/cakes 时会发生什么?

我们是否将初始的cakes 链接保留在根目录以实现反向兼容性?如果没有,我们如何为被告知“去根,寻找蛋糕”的可怜的小代理进行“重定向”?

我错过了什么?

【问题讨论】:

Furtherreadingforanyoneinterested. 【参考方案1】:

@Benjol

您必须避免针对特定 URI 对客户端进行编程。当你描述一个链接时,主要的重要性有它的意义,而不是 URI 本身。您可以随时更改 URI,但这不会破坏您的客户端。

我会这样改变你的例子:

"link": 
  "rel":   "collection http://relations.your-service.com/cakes",
  "href":  "http://tonis.com/cakes",
  "title": "List of cakes",
  "type":  "application/vnd.yourformat+json"

如果有一个客户端在使用你的服务,它需要了解:

链接结构本身 链接关系(在本例中为“集合”,即 RFC 和 “http://relations.your-service.com/cakes”这是您的域名 具体链接关系)

在这种情况下,客户端只需取消引用“href”属性指定的地址并显示蛋糕列表即可。稍后,如果您更改了 cake list provider URI,客户端将继续工作,这意味着客户端仍然理解您的媒体类型的语义。

附言

查看已注册的链接关系属性: http://www.iana.org/assignments/link-relations/link-relations.xml Web 链接 RFC:https://www.rfc-editor.org/rfc/rfc5988

【讨论】:

【参考方案2】:

好吧,我也不是 REST 专家,我最近一直在阅读很多相关的东西,所以我要写的不是我的经验或观点,而是我所读内容的总结,尤其是REST In Practice书。

首先,您无法避免在客户端和服务器之间达成一些初步协议,REST 的目标是让他们在与他们双方相关的最起码的事情上达成一致,并让各方关心他们自己的东西。例如,客户端不应该关心链接布局或数据如何存储在服务器上,服务器不应该关心客户端的状态。他们事先(即在交互开始之前)达成的共识就是上述书籍的作者所说的“域应用协议”(DAP)。

关于 DAP 的重要一点是它是有状态的,即使 HTTP 本身不是(因为任何客户端-服务交互至少有状态,开始和结束)。这种状态可以用“客户下一步可以/可能/预期做什么”来描述:“我已经开始使用该服务,现在怎么办?好的,我可以搜索项目。搜索这个项目,下一步是什么?好的,我可以点这个那个……等等”

超媒体内容类型的定义是能够处理数据交换和交互状态。正如我已经提到的,状态是根据可能的动作来描述的,并且来自 REST 中的“资源”,所有动作都是根据可访问资源来描述的。我想,您已经看到了首字母缩略词“HATEOAS(超媒体作为应用程序状态的引擎),所以它显然是这个意思。

因此,为了与服务交互,客户端使用他们都理解的超媒体格式,可以是标准的、本土的或混合的(例如基于 XML/XHTML)。除此之外,他们还必须共享协议,这很可能是 HTTP,但是由于标准中省略了一些细节,因此必须有一些使用习惯,例如“使用 POST 创建资源和 PUT 更新” .此外,此类协议将包括服务的入口点(同样,在可访问资源方面)。

这三个方面完全定义了域协议。特别是,客户端在开始使用服务之前不应该知道任何内部链接,或者在交互完成后记住它们。因此,内部导航的任何更改,例如将/cakes重命名为/f5d96b5c,只要客户遵守初始协议并通过前门进入商店,就不会影响客户。

【讨论】:

以上是关于为 RESTful(超媒体)API 编写客户端的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Refit Client for RESTful API:如何划分客户端

flask编写RESTful API

RESTful Web API 理解

如何落地业务建模 将模型实现为RESTful API

如何落地业务建模 将模型实现为RESTful API

DropWizard/Jersey API 客户端