【问题标题】:REST - What exactly is meant by Uniform Interface?REST - 统一接口到底是什么意思?
【发布时间】:2014-09-30 02:37:48
【问题描述】:

Wikipedia has:

统一界面

统一接口约束是任何 REST 服务设计的基础。[14]统一的接口简化并解耦了架构,使每个部分都可以独立发展。该接口的四个指导原则是:

资源识别

在请求中标识单个资源,例如在基于 Web 的 REST 系统中使用 URI。资源本身在概念上与返回给客户端的表示是分开的。例如,服务器可以从其数据库中以 HTML、XML 或 JSON 的形式发送数据,这些都不是服务器的内部表示,无论如何都是同一个资源。

通过这些表示来操纵资源

当客户端持有资源的表示,包括任何附加的元数据,它有足够的信息来修改或删除资源。

自我描述信息

每条消息都包含足够的信息来描述如何处理该消息。例如,调用哪个解析器可以由 Internet 媒体类型(以前称为 MIME 类型)指定。响应还明确指出它们的可缓存性。

超媒体作为应用程序状态的引擎(A.K.A. HATEOAS)

客户端仅通过服务器在超媒体内动态识别的动作(例如,通过超文本中的超链接)进行状态转换。除了应用程序的简单固定入口点外,客户端不假定任何特定资源可用于任何特定资源,而不是先前从服务器接收到的表示中描述的资源。

我正在听一个关于这个主题的讲座,讲师说:

“当有人使用我们的 API 时,如果您能够获取客户对象并且您知道有订单对象,那么您应该能够以与获取客户对象相同的模式获取订单对象。这些 URI 看起来会很像。”

这让我觉得是错误的。 与其说是 URI 的外观或一致性,不如说是使用 URI 的方式(识别资源,通过以下方式操作资源)陈述、自我描述的消息和仇恨)。

我认为这根本不是统一接口的意思。究竟是什么意思?

【问题讨论】:

  • 我相信他们的意思是,如果您可以通过路由为 /api/customer 的端点获取客户信息,那么您可以推断要获取订单信息,您可以向 /api/order 发出请求
  • @vesuvious 这正是我的意思。那是错误的。 REST API 是发现 API 而非推理 API。客户不应做出任何推论。如果是这样,则客户端和服务器耦合得太紧了。
  • @JohnSaunders 我不确定你的意思。 REST API 的定义是发现 API。
  • @jon 我不明白你的意思。你的cmets一直很神秘。我是不是傻了,这整件事完全错了?我真的很想理解这一点。如果你不知道那也没关系。
  • RESTful 架构的严格定义是它必须是可发现的……不幸的是,大多数 API 都声称是 RESTful 并且未能满足此约束。在现实世界中,许多不是严格 RESTful 的 API 都称为 REST,因为它们使用 HTTP 和 JSON 或 XML,有时在 URL 中有参数,有时使用 HTTP 动词/方法。有些人使用超媒体 API 作为一个术语来表示 API 是真正的 RESTful。对于@JohnSaunders,您应该查看 github 的 api 以查看可发现的 API

标签: rest definition uniform-interface


【解决方案1】:

使用接口将类与其依赖项的实现分离是一个相当古老的概念。在 REST 中,您使用相同的概念将客户端与 REST 服务的实现分离。为了定义这样的接口(客户端和服务之间的契约),您必须使用标准。这是因为如果您想要一个互联网规模的 REST 服务网络,您必须强制执行全局概念,例如标准,以使它们相互理解。

  • 资源识别 - 您使用 URI (IRI) 标准来识别资源。在这种情况下,资源是 Web 文档。

  • 通过这些表示操作资源 - 您使用 HTTP 标准来描述通信。因此,例如 GET 意味着您要检索有关 URI 标识资源的数据。您可以使用 HTTP 方法和 URI 来描述操作。

  • 自描述消息 - 您使用标准 MIME 类型和(标准)RDF vocabs 使消息自描述。因此客户端可以通过检查语义来找到数据,而不必知道服务使用的应用程序特定的数据结构。

  • 超媒体作为应用程序状态的引擎(又名 HATEOAS)- 您使用超链接和可能的 URI templates 将客户端与特定于应用程序的 URI 结构分离。您可以使用语义注释这些超链接,例如IANA link relations,所以客户会明白他们的意思。

【讨论】:

  • 通俗易懂的好解释
  • 因为它很简单。 :-)
  • 当然我听说过接口,我很清楚通过契约(接口)解耦实现的概念。我认为我缺少的是统一接口仅意味着这 4 个约束(资源识别、通过表示进行操作、自我描述消息和仇恨)。
  • "您可以使用 HTTP 方法和 URI 来描述操作。"仅当 URI 是基于 HTML 的。 (mailto 是不基于 HTML 的 URI - 它们是基于 mailto 的。)
  • 统一接口在哪里?您描述了其他原则,但询问者正在寻找统一接口...
【解决方案2】:

任何 ReSTful 架构都应遵守的统一接口约束实际上意味着,除了数据之外,服务器响应还应宣布可用的操作和资源。

chapter 5 of his dissertation 中,Roy Fielding(ReST 架构风格的创始人)指出,使用统一接口的目的是:

简化和改进全局架构和交互的可见性

换句话说,查询资源应该允许客户端在事先不知道的情况下请求其他操作和资源

JSON-API 规范就是一个很好的例子:

{
  "links": {
    "self": "http://example.com/articles",
    "next": "http://example.com/articles?page[offset]=2",
    "last": "http://example.com/articles?page[offset]=10"
  },
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        }
      }
    },
    "links": {
      "self": "http://example.com/articles/1"
    }
  }]
}

只要分析这个单一的响应,客户就知道:

  1. 查询了什么(本例中为articles
  2. 如何结构化文章对象(idtitleauthorcomments
  3. 如何检索相关对象(即authorcomments 列表)
  4. 还有更多文章(10,基于当前响应长度和分页链接)

我希望这会有所帮助。
对于那些对这个话题充满热情的人,我强烈推荐阅读Roy Thomas Fielding's dissertation

【讨论】:

    【解决方案3】:

    您的问题有点宽泛,您似乎要求重述您的定义。您是在寻找示例,还是您不了解具体说明的内容。

    我同意以下内容:

    这些 URI 看起来很像

    根本上是错误的。为了满足统一接口约束,URI 不需要看起来彼此相似。需要提供一种统一的方式来发现标识资源的 URI。这种统一的方式对每种消息类型都是唯一的,并且必须有一些约定的格式。例如,在 HTML 中,一个文档资源通过一个简单的标签链接到另一个文档资源:

    <a href="URI of related resource" rel="defined relationship">fallback relationship</a>
    

    HTTP 服务器将 html 作为文本/html 资源类型返回,浏览器有约定的解析方式。锚标记是具有相关资源唯一标识符的超媒体控件 (HATEOAS)。

    唯一没有涉及的一点是操纵。 HTML 有另一个很棒的例子,form 标签:

    <form action="URI" method="verb">
      <input name=""></input>
    </form>
    

    同样,浏览器知道如何解释此元信息以定义在 URI 处作用的资源的表示。不幸的是,HTML 只允许您对动词进行 GET 和 POST...

    在基于 JOSN 的服务中更常见的是,当您检索 Person 资源时,很容易操纵该表示,然后将其 PUT 或 PATCH 直接返回到它的规范 URL。修改它不需要预先存在的资源知识。现在,当我们编写客户端代码时,我们都会被这样一种想法所包围,即我们实际上确实需要在使用它之前知道形状……但这实际上只是为了使我们的解析器高效且简单。我们可以制作解析器来分析资源每个部分的语义,并通过解释修改的意图来修改它。 IE:使人大 10 岁的命令将解析资源以查找年龄,识别年龄,然后将 10 年添加到该值,然后将该资源发送回服务器。拥有期望年龄位于 $.age 的 JSON 路径的代码是否更容易?绝对...但不是特别需要。

    【讨论】:

    • 谢谢克里斯。不过我不太明白你的意思。什么是需要统一的“接口”?我在想它是协议,即http。但是听起来您是在说响应也必须是统一的,即商定的信息表示格式。但是“组件之间的统一接口”对我来说听起来就像它只是需要统一的协议。你怎么看?
    • 我认为您听到的是“统一界面”并认为是统一的界面。他只是使用术语“统一接口”作为 4 个子约束的分组概念:资源识别、通过这些表示对资源进行操作、自描述消息、HATEOAS。任何遵循 4 个约束的东西都是“统一接口”。不要将术语分开进行分析,只需按原样接受即可。 HTTP 是一个很好的实现组件,因为它包含 URL 和超文本
    【解决方案4】:

    好的,我想我明白这意味着什么。

    来自菲尔丁的论文:

    REST 架构风格与其他基于网络的风格的主要区别在于它强调组件之间的统一接口(图 5-6)。通过将软件工程的通用性原则应用于组件接口,简化了整个系统架构并提高了交互的可见性。

    他是说组件之间的接口必须相同。 IE。客户端和服务器以及任何中介之间,所有这些都是组件。

    【讨论】:

    • 然而,我不记得他在哪里说过以前的架构如何在组件之间没有统一的接口。我曾在许多系统上工作过,其中一个 SOAP 服务调用另一个 SOAP 服务的特性来执行其职责。我相信这就是所谓的“SOA”。
    • Well Rest 显然具有其他架构风格等的属性。它并不都是新奇的。此外,肥皂和休息并不是相互排斥的。安宁的服务可以用肥皂来做到这一点(据我所知)。不过,我认为统一接口的独特之处在于它是一种约束,是一种休息的要求,与其他架构风格不同。我相信他的意思是“不要将数据与其他接口相结合,对所有参与组件使用相同的接口。”
    • 大多数 SOAP 服务都错过了 HATEOAS。他们都错过了资源识别。您总是必须在 SOAP 中调用远程对象上的方法来检索任何内容。您从未直接检索过它们。自我消息传递是不可能的,始终需要 WSDL。这并不是说 WSDL 不好或难以使用……它们只是打破了“统一接口”的约束
    • @ChrisDaMour - WSDL 本身不是接口标准吗?即 WSDL 是根据标准编写的,因此客户端可以读取它以了解服务器上可用的操作。因此不存在耦合... 服务器在预期的端点提供 WSDL,因此客户端可以与服务器耦合。为什么这不是一个统一的接口?
    • 因为soap动作的结果不是另一个类似wsdl的东西可以被执行。此外,我熟悉的所有 soap 客户端实现都不会在运行时检索 wsdl,而是在客户端时检索。我可能确信这是客户端实现的限制,但这本质上是不安的,这是由肥皂动作返回静态消息而不是具有进一步超媒体控制的资源这一事实触发的。许多“休息”客户端这样做是为了跳转到已知的 url,而不是在运行时从根资源中发现操作
    猜你喜欢
    • 1970-01-01
    • 2010-12-01
    • 2014-06-02
    • 2017-08-07
    • 2017-07-20
    • 2014-09-23
    • 2014-07-25
    • 2012-09-17
    • 1970-01-01
    相关资源
    最近更新 更多