1

我很困惑 REST api 如何既可以是超文本驱动的,又可以是机器可读的。假设我设计了一个 API,一些端点列出了集合的内容。

GET /api/companies/

服务器应返回包含公司资源的列表,例如:

/api/companies/adobe
/api/companies/microsoft
/api/companies/apple

一种方法是生成带有<a>指向相应资源的链接的超文本 (html) 页面。但是,我还想让非浏览器客户端更容易阅读此列表。例如,某些客户可能希望用公司填充下拉 gui。在这种情况下,返回 html 文档是不合适的,最好返回 JSON 或 XML 格式的列表。

我不清楚 REST 风格如何同时满足两者。是否有对浏览器和非浏览器客户端都很好的 REST api 的实用解决方案或示例?

4

3 回答 3

3

您正在寻找的东西现在被称为 HATEOAS API。有关示例,请参见此问题:HATEOAS 的实际示例(REST 架构)

最初由 Roy Fielding 定义的 ReST 架构风格将“超文本作为应用程序状态的引擎”规定为架构约束之一。然而,当人们开始将“RESTful API”等同于“正确使用 HTTP 动词”(如果幸运的话,再加上一点),这个概念或多或少地“在翻译中迷失了”。(编辑:为我的断言提供信任是什么是 RESTful 编程?第一个和第二个最高评分的答案。第一个只讨论 HTTP 动词)。

关于你的问题的一些想法:(主要是因为这个主题让我着迷)

在 HATEOAS 中,具有精确含义的标准化媒体类型非常重要。通常认为最好尽可能重用现有媒体类型,以便从对此的一般理解和工具中受益。一种流行的方法是使用 XML,因为它提供了数据的通用结构和定义语义的方法,即通过 XML 模式或名称空间。在考虑 HATEOAS 时,XML 本身或多或少是没有意义的。这同样适用于 JSON。

对于支持链接,您希望选择一种媒体类型,它要么支持“本机”链接(即text/htmlapplication/xhtml+xml),要么允许定义文档中的哪些部分必须通过一些嵌入的元数据解释为链接,例如 XML 可以与 for例如 XLINK。我认为您不能使用application/json,因为 JSON 本身没有定义元数据的预定义位置。我确实认为可以设计基于 json 的媒体类型 - 称之为application/x-descriptive-json- 预先定义返回的 JSON 文档必须包含“header”和“body”属性,其中 header 可能包含进一步指定的元数据。您还可以为 JSON 设计一种媒体类型,以支持嵌入式链接。更简单的媒体类型,更少的可扩展性。如果我描述的两件事都已经以某种形式存在,我不会感到惊讶。

为了对浏览器和非浏览器客户端都友好,只需要尊重Accept标题即可。您必须假设请求 text/html 的客户对 text/html 非常满意。这可能是不将text/html其用作非浏览器 API 入口点的媒体类型的论据。原则上,我认为如果您唯一想要的是链接,它可以工作。非浏览器客户端可以很好地使用良好的 HTML 标记。HTML 还定义了进行分页的方式,通过rel="next", rel="previous".

我看到的浏览器和非浏览器的单一媒体类型的三个最大问题是:

  1. 您必须确保在输出所有站点 html 时考虑到非浏览器消耗,即嵌入足够的元数据。也许在某些地方添加隐藏链接。这与考虑视障人士的可访问性有点可比:尽管现在,您正在为无法阅读英语或任何自然语言的消费者进行设计。:)
  2. 可能有很多标记和内容基本上与非浏览器客户端无关。想想重复的页眉和页脚文本,导航区域之类的东西。
  3. HTML 可能只是缺乏您需要的表现力。原则上,只要您“想出”一些特定于您的网站的约定(即表示rel="original-image指向全尺寸原始图像的链接),那么您就不再严格执行 HATEOS(至少,这是我的理解)。HTML 没有为元素定义新含义的空间。XML 可以。

解决问题三的方法可能是使用 XHTML,因为 XHTML 凭借其 XML 特性,确实允许通过名称空间指定新类型的元素。

我看到@robert_b_clarke 提到了与本讨论相关的 Microformats。这确实是一种尝试提高非人类代理可访问性的方法。从技术角度来看,主要问题在于它本质上依赖于“带外”信息。微格式不是text/html规范的一部分。在某种程度上,这相当于说:“嘿,如果我说有一个类型为 A 和 id X 的资源,你可以在 mysite.com/A/X 上访问它。” 我给出的示例rel=original-image也可以称为微格式。但这是一条路要走。“在您的 API 文档中声明:我们提供格式良好的 text/html。我们的 text/html 还嵌入了以下微格式:...”您甚至可以定义自己的微格式。

我认为以下演示文稿是对 HATEOAS 的一个很好的脚踏实地的解释: http ://www.slideshare.net/apigee/hateoas-101-opinionated-introduction-to-a-rest-api-style

编辑:

我现在才读到HTML5 微数据(因为 @robert_b_clarke)。似乎 HTML5 确实提供了一种方法来提供超出标准 HTML 标签所能提供的附加信息。考虑一下我写的日期。:) 编辑编辑:这只是一个草稿,唷。;)

编辑 2

重新采用“描述性 JSON”格式:刚刚公布了http://jsonapi.org/。他们已经申请了自己的 mime 类型。由 Yehuda Katz (Ember.js) 和 Steve Klabnib 撰写,他们正在编写Designing Hypermedia API's .

于 2013-05-02T10:59:55.487 回答
1

客户端可以使用HTTPAccept标头来请求特定内容类型的响应。例如,您的 REST API 客户端可能会使用以下标头请求 JSON 数据:

GET http://yourdomain.com/api/companies
Accept: application/json

因此,您的服务器应用程序可以根据 Accept 标头的值为相同的 URL 提供 JSON 或 HTML。当然,您所有的 REST 客户端应用程序都必须包含该标头,这可能实用,也可能不实用。

有许多替代方法,其中之一是将相同的 XHTML 内容提供给浏览器和客户端应用程序。您可以使用HTML5 微数据微格式在 HTML 中嵌入结构化数据。这种方法有许多局限性。API 客户端请求将导致更大、更复杂的响应,因为它们将包含大量只能由 Web 浏览器使用的内容。您可能希望强制执行的行为还有其他差异。例如,您可能希望对受保护资源的未经授权的 GET 请求导致机器客户端的 HTTP 401 响应,并重定向到 Web 浏览器的登录页面。

您可能会发现,最简单的方法是不那么有原则,通过单独的 URL 为您的资源的人类友好和机器友好版本提供服务

http://yourdomain.com/companies
http://yourdomain.com/api/companies
于 2013-05-02T09:39:23.193 回答
0

我已经看到这个问题回答了几种方式。一些开发者添加了一个请求参数来指示响应的格式,如/api/companies/?rtnType=json。这种方法在小型应用中可能是可以接受的。不过,这与真正的 RESTful 神学背道而驰。

更好的方法(至少在 Java 中)是使用 Spring Framework 之类的东西。Spring 可以根据 HTTP 请求中的媒体类型提供动态响应格式。《Spring in Action》(Walls,2011 年)一书在第 11 章对此进行了很好的解释。还有类似的方法可以在不破坏 REST 的情况下在其他语言中完成动态响应格式化。

于 2013-05-02T02:01:12.333 回答