REST:通过不同的标识符更新资源吗?

时间:2018-09-03 11:49:16

标签: rest api

假设我们有一个user资源,看起来像这样:

{
  id: 1,
  identifier: 'U00001V002',
  name: 'bob'
}

更新该资源的好方法是:

PUT /users/1
{
  name: 'alice',
  ...
}

现在,如果我们的客户不知道资源ID(1)但知道标识符(也是唯一的)怎么办?

如何实现并仍然符合REST?

1 个答案:

答案 0 :(得分:1)

REST是一种体系结构样式,如果严格遵循的话,将允许客户端使自己与API /服务脱钩。这样一来,后者就可以自由发展而不会破坏客户端,从而使它们变得更加可靠。但是,只有遵循以下约束条件才能获得此属性

  • 遵守基础传输协议(HTTP),以提高跨域互操作性的可能性
  • HATEOAS(关注有意义的链接关系名称和API /服务器提供的URI支持)
  • 关注媒体类型(交换的媒体类型语法和语义的合同)

完全。不幸的是,仅部分遵循它并不能产生它所提供的所有好处。

根据RFC 7231 PUT

  

PUT方法请求创建目标资源的状态或将其替换为由请求消息有效负载中包含的表示形式定义的状态。

松散地说,PUT要求如果某个资源的前一种表示形式没有违反任何语义限制,则将其替换为PUT请求收到的有效负载。但是,服务器可以根据需要随意添加或修改请求,即,根据需要添加链接和其他数据。

作为应用程序状态(HATEOAS)引擎的超文本是REST施加在表上的少数约束之一。它要求API /服务器向客户端提供客户端可以使用的URI。与我们每天使用的Web相似,可以使用有意义的关于URI的内容或意图的描述来注释链接,如果感兴趣的话会被我们的人类点击。该概念也应转换为REST应用程序。 URI随附的描述性文本称为链接关系名称,客户​​端应使用它来确定是否调用URI或帮助客户端确定何时调用哪个URI。它应该对客户尽可能有意义,并且可以以某些媒体类型,通用标准或领域知识来指定。即一个可分页的集合可以使用诸如nextprevfirstlast之类的链接关系,使客户可以在不需要客户的情况下分页浏览集合的不同元素知道确切的URI。它将仅基于链接关系名称来调用URI。当服务器更改其URI结构时,此技术可帮助客户端增强鲁棒性。很明显,如果服务器更改了URI结构,则解析URI以确定意图的客户端将很容易中断,使用链接关系的客户端实际上并不关心URI的具体拼写,因为URI仅用于调用再次使用API​​。

根据Fielding的blog post之一,API应该为客户端提供进行任务所需的所有信息。这包括提供客户端可以从当前状态开始调用的所有必要链接。这消除了客户端解析和解释URI以及稍后生成它们以执行请求的负担。服务器的响应可能包含以下链接:

{
    "name": "bob",
    ...
    "_links": [
        "self": {
            "href": "http://.../users/1"
        },
        "identifier": {
            "href": "http://.../users/U00001V002"
        },
        "friends": [
            "tim": {
                "href": "http://.../users/2"
            },
            "sam": {
                "href": "http://.../users/3"
            },
            ...
        ],
        ...
    ]
}

要返回的链接或信息完全是特定于域的。仅限于JSON即是一个不好的选择,因为JSON缺乏对链接的支持,而且无法描述实际内容的语义。

以上表示可能导致客户假定某些资源具有某种类型,然后仅为该特定类型创建编组器。如果添加新字段,或者遗漏或重命名旧字段,则此类系统可能会轻易中断。代替使用typed resources meaningful to them API的客户端,应该设计各种媒体类型。菲尔丁甚至指出

  

REST API应该花费其几乎所有的描述性精力来定义用于表示资源和驱动应用程序状态的媒体类型,或者为现有标准媒体类型定义扩展的关系名称和/或启用超文本的标记

媒体类型是REST体系结构中客户端和服务器之间的耦合部分。代替客户端直接耦合到相应的API(因此,每当API更改时就需要更新),服务器和客户端都耦合到大量的媒体类型,并协商他们了解的媒体类型。与浏览器类似,应用程序稍后可能会通过插件即时添加对新媒体类型的支持,甚至不需要重启。

对定义明确的媒体类型的关注进一步帮助客户端和服务器避免以后破坏更改。即无需对某个API进行版本控制,而是可以对媒体类型进行版本控制,因为它定义了交换的标头和有效载荷的语法和语义。 HTML,即决定保持向后兼容,以避免破坏无法更新到新版本规范的旧客户端。

诸如application/atom+xmlapplication/hal+json之类的某些媒体类型在HATEOAS支持方面提供了某些好处。但是,对于大多数应用程序来说,它们可能太通用了。 application/collection+json,即也仅对返回的集合有用。根据Fielding的说法,媒体类型应具有足够的通用性,以便可以跨域重用,但又应具有足够的特定性以便在某些域中可用。即要交换用户信息,可以使用text/vcard或其他变体之一(例如:XML,JSON),而不是创建新的以用户为中心的媒体类型。可以找到here

已定义的媒体类型的列表

您可能希望看到,REST体系结构中涉及的每个步骤都集中于将客户端与API分离,并尽可能保持该体系结构中不同对等方的互操作性。

如上所述,尽管URI必须准确标识一个资源,但是资源的内容可能会通过多个URI公开。因此,您可以按照建议的方式发送多个链接,客户端可以简单地调用这些链接,包括有意义的链接关系名称作为对客户端的响应。从长远来看,一种更合适的REST方法将包括切换到媒体类型支持,并描述客户端或服务器可能期望的语法和语义。