REST,超文本和非浏览器客户端

时间:2013-05-02 01:09:04

标签: html json http rest

我很担心REST api既可以是hypertext driven,也可以是机器可读的。假设我设计了一个API,一些端点列出了一个集合的内容。

GET /api/companies/

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

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

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

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

3 个答案:

答案 0 :(得分:3)

您现在正在寻找的是HATEOAS API。请参阅此问题以获取示例:Actual examples for HATEOAS (REST-architecture)

Rest架构风格,最初由Roy Fielding定义,规定&#34;超文本作为应用程序状态的引擎&#34;作为建筑约束之一。然而,这个概念或多或少地在翻译中丢失了#34;当人们开始等待&#34; RESTful API&#34;用&#34;使用HTTP动词吧#34; (加上一点,如果你很幸运的话)。 (编辑:为我的断言提供信任是What exactly is RESTful programming?中第一和第二高的答案。第一个只讨论HTTP动词。)

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

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

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

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

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

  1. 您必须确保输出所有网站html时考虑到非浏览器消费,即嵌入足够的元数据。也许在某些地方添加隐藏的链接。从考虑视障人士的可访问性来看,它有点可比:现在,您正在为不能阅读英语或任何自然语言的消费者进行设计。 :)
  2. 可能存在大量与非浏览器客户端基本无关的标记和内容。考虑重复页眉和页脚文本,导航区域的那种事情。
  3. HTML可能只是缺乏您需要的表现力。原则上,一旦你去&#34;想起来&#34;一些特定于您网站的约定(即说rel="original-image表示指向全尺寸原始图片的链接),然后您不再严格执行HATEOS(至少,这是我的理解) 。 HTML没有为元素定义新含义的空间。 XML确实。
  4. 问题三的解决方法可能是使用XHTML,因为XHTML凭借XML,允许通过命名空间指定新类型的元素。

    我看到@robert_b_clarke提到了Microformats,这与本次讨论有关。这确实是尝试改善非人类代理人的可访问性的一种方式。从技术角度来看,它的主要问题在于它基本上依赖于带外&#34;带外&#34;信息。微格式不是text/html规范的一部分。在某种程度上,它可以说:&#34;嘿,如果我说那里有A型和id X的资源,你可以在mysite.com/A/X.&访问它。 #34;我用rel=original-image给出的例子也可以称为微格式。但这是一种方法。 &#34;陈述您的API文档:我们提供格式良好的文本/ HTML。我们的text / html还嵌入了以下微格式:...&#34;你甚至可以定义自己的。

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

    编辑:

    我现在才读到HTML5 microdata(因为@robert_b_clarke)。看起来HTML5确实提供了一种方法,可以提供超出标准HTML标签的额外信息。考虑我写的日期。 :)编辑编辑:它只是一个草稿,phew。 ;)

    编辑2

    Re a&#34;描述性JSON&#34;格式:刚刚宣布http://jsonapi.org/。他们申请了自己的哑剧类型。由Yehuda Katz(Ember.js)和Steve Klabnib撰写的Designing Hypermedia API's撰写。

答案 1 :(得分:1)

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

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

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

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

您可能会发现最简单的方法是减少原则,并通过单独的网址为人力资源和机器友好版本的资源提供服务

http://yourdomain.com/companies
http://yourdomain.com/api/companies

答案 2 :(得分:0)

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

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