REST——统一接口的确切含义是什么?



Wikipedia has:

统一接口

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

资源标识

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

通过这些表示操作资源

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

自描述信息

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

超媒体作为应用状态引擎(又名HATEOAS)

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

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

"当有人访问我们的API时,如果您能够获取客户对象,并且您知道有订单对象,那么您应该能够使用与获取客户对象相同的模式获取订单对象。这些URI将看起来彼此相似。"

我认为这是错误的。问题不在于URI是什么样子的,也不在于URI的一致性,而在于URI的使用方式(标识资源、通过表示操作资源、自描述消息等)。

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

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

  • 资源标识—您使用URI (IRI)标准来标识资源。在这种情况下,资源是一个web文档。

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

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

  • 超媒体作为应用程序状态的引擎(又名HATEOAS) -您使用超链接和可能的URI模板来将客户端与应用程序特定的URI结构解耦。你可以用语义注释这些超链接,例如IANA链接关系,这样客户端就能理解它们的意思。

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

在他的论文第5章("表征状态转移")中,Roy Fielding指出使用统一接口的目的是:

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

换句话说,查询资源应该允许客户端请求其他操作和资源,而不需要事先知道它们

JSON- api 规范(jsonapi.org)提供了一个很好的示例,以JSON响应的形式响应http://example.com/articles上的(假设的)GET HTTP请求:
{
  "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. 查询哪些实体 ("文章"
  2. 这些实体是如何构成的(文章有字段:id, title, author, comments);
  3. 如何检索相关实体(即authorcomments);
  4. 有更多的"文章"类型的实体(10,基于当前响应长度和分页链接)。

对于那些对这个话题充满热情的人,我强烈建议阅读罗伊·托马斯·菲尔丁的论文!

你的问题有点宽泛,你似乎要求重述你的定义。你是在找例子,还是你不明白具体说明的事情。

我同意这句话:

这些URI看起来很像

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

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

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

唯一没有提到的一点是操纵。HTML有另一个很棒的例子,表单标签:

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

,浏览器知道如何解释这个元信息来定义在URI上操作的资源的表示。不幸的是,HTML只允许对动词进行GET和POST…

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

我想我明白它的意思了。

From Fieldings dissertation:

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

他说组件之间的接口必须是相同的。Ie。

最新更新