如何为机器和人类使用一个 REST API



我对使用 REST API 构建 Web 服务感兴趣。我一直在阅读有关HATEOAS的文章,许多示例通过将它与人类上网时的行为进行比较来解释这个概念。这让我在想,为什么不以人类和机器都可以轻松使用的方式构建 REST API?

例如,我有一个小部件的内部模型,这个小部件具有零件号、价格等属性。当机器要求小部件列表时,我可以返回 JSON 表示形式。

{
    widgets: [
        {
            id: 1,
            part_number: "FOO123",
            price: 100,
            url: "/widget/1"
        },
        {
            id: 2,
            part_number: "FOO456",
            price: 150,
            url: "/widget/2"
        },
        {
            id: 3,
            part_number: "FOO789",
            price: 200,
            url: "/widget/3"
        },
        ...
    ]
}

当一个人通过他/她的网络浏览器请求相同的列表时,似乎我应该能够采用相同的内部模型并对其应用不同的视图以生成 HTML 响应。(当然,我会用其他页面元素来装饰 HTML 响应,如页眉、页脚等。

这是一个明智的设计吗?为什么或为什么不呢?有没有真正这样做的热门网站?

我看到的最大缺点是用户没有明显的方法来删除资源。在我的用例中,我不会让用户修改或删除资源,所以这不是一个交易破坏者,但总的来说,你会如何处理这个问题?

> @mehaase

首先,我建议使用已注册的JSON超媒体格式之一:

  • 集合+JSON:http://amundsen.com/media-types/collection/format/
  • Collection.next+JSON:http://code.ge/media-types/collection-next-json/
  • HAL - 超文本应用语言:http://stateless.co/hal_specification.html

它们都提供了显式语义,用于创建具有语义链接关系的链接。

例如,使用 Collection(.next)+JSON,您可以像这样表达您的小部件:

{"collection": {
  "version": 1.0,
  "items": [{
    "href": "/widget/1",
    "data": [{
      "name": "id",
      "value": 1,
      "prompt": "ID"
    }, {
      "name": "part_number",
      "value": "FOO123",
      "prompt": "Part number"
    }, {
      "name": "price",
      "value": 100,
      "prompt": "Price"
    }],
    "links": [{
      "rel": "self",
      "href": "http://...",
    }, {
      "rel": "edit",
      "href": "http://..."
    }]
  }]
}}

这为您提供了几个优势:

  • 您无需重新发明轮子来指定链接
  • 您可以自由使用所有已注册的链接关系类型:http://www.iana.org/assignments/link-relations/link-relations.xml
  • 根据您的数据结构,您可以轻松使用上述格式的集合/项目语义
  • 如果需要,您也可以描述输入表单

正如你从例子中看到的,它有足够的信息来转换为HTML(或其他格式)。

我看到的最大缺点是用户没有明显的方法 以删除资源。在我的用例中,我不会让用户 修改或删除资源,因此这不是交易破坏者,而是在 一般你会如何处理?

对于此读取"编辑"链接关系规范,它意味着可以删除资源。

你可以做几件事,但第一个前提是现代的"通用"Web浏览器真的是糟糕的REST客户端。

如果你

的大部分交互都是由JavaScript保护和管理的,如果你写了一个"富客户端",可以说你更多地依赖于JS生成的请求,而不仅仅是链接,表单和后退按钮,那么它可以是一个更好的REST客户端。

如果您坚持使用表单和链接的通用浏览器体验,则可以通过重载 POST 来绕过缺少其他 HTTP 谓词的问题。你失去了中介机构的一些保证。DELETE 是幂等的,POST 不是,这会产生影响,但它不是毁灭性的,你只需要解决它。你可以用 POST 做幂等的事情,但中介不会"知道"它们是幂等的,所以他们不能假设它是幂等的。

如果你最终不得不去"POST uber alles",你要么将你的机器客户端限制在同一个api上,要么提供并行服务——那些由POST愚蠢的客户端使用,以及其他那些拥有全部可用范围的服务。

也就是说,如果您选择基于 XML 的超媒体格式,那么您可以做的是将 XSL 转换添加到 XML 有效负载。浏览器将在有效负载上运行 XSL,创建您喜欢的漂亮页面(页眉、页脚、足够的 JS 来窒息马等),而机器将忽略它的这一方面,只关注给定的数据。

在这方面为您提供"两全其美"。

您始终可以构建 REST API,然后围绕它构建自己的、人性化的 Web 应用程序。这是一种常见做法,因为您具有开箱即用的功能和面向开发人员的可扩展系统。

只需

将HTML与RDFa一起使用即可。因此,人类可以阅读HTML,机器可以阅读RDFa注释。你需要一个像 hydra 这样的 REST 词汇来注释链接,以及其他词汇,如 schema.org 来注释内容。

为不同类型的客户端使用不同媒体类型的另一种选择,例如用于人类的 HTML 和用于机器的 JSON-LD。

最新更新