带有链接的REST资源表示,与PUT和GET兼容

时间:2013-01-22 17:05:18

标签: api rest

我被要求设计和实现RESTful API,并且一直在研究最佳实践,但到目前为止只有一个关于资源表示的愚蠢概念。我发现的大多数可用示例似乎都非常关注使用一系列GET来连接结构的API客户端。

我看过:

http://www.restapitutorial.com/media/RESTful_Best_Practices-v1_1.pdf

http://www.youtube.com/watch?v=HW9wWZHWhnI

在其他在线资源中(我限于2个链接抱歉不能列出所有这些)。它们都很棒,但并没有真正解决我的设计问题。

大多数最佳实践文档都提出了两件让我看起来有点冲突的事情:

1)REST服务应将数据关系表示为资源之间的链接

2)来自客户端的“PUT”请求应该是完整的表示形式,其形式与服务器上显示的表示形式相同。

从我的角度来看,问题在于链接以及典型资源中的其他一些属性是只读的,因此无法更新。该服务器可以预期它们按原样运行,如果它认为客户端正在尝试更新它们,则会返回错误。事实上,当我查看JSON中表示的典型资源时,其中大部分是逻辑上不能/不应该替换的数据。 E.g。

{
 "link": { "rel":"self", "href":"http://example/project/12345" },
 "team": {
    "link": { "rel":"self", "href":"http://example/project/12345/team" },
    "title": "The project team"
  },
  "title": "The Big Project"
}

此处最多只有两个标题文本可以写入此资源上的客户端(团队成员资格可以通过团队链接进行更改)。

所以我应该要求PUT完全按原样包含所有“链接”元素,这些元素纯粹是逻辑和只读的(注意在示例中,团队无法重新链接,因为资源定义了它作为项目的团队 - 在这种情况下可以改变,但对于许多具有更严格的集装箱船的资源类型,这不适用)?

是否有标准模式或反模式用于在REST中使用多个链接表示资源?我没有被要求提供特定的REST变体,例如HATEOAS,尽管我倾向于在可能的情况下瞄准理论上的“正确性”。换句话说,如果“官方”REST将期望客户将整个资源,链接和所有资源投入,那么这可能就是我要做的。

支持GET和PUT的真实世界复杂的非叶子REST资源的一些示例,因此必须解决这个问题,我们将非常感激。当我搜索时,我得到了很多意见,并且很多例子显示了GET的工作原理。 。 。但到目前为止,我还没有看到一个记录良好的例子显示PUT除了一个简单的叶子资源(即一个不包含任何链接,除了自我引用之外)。

2 个答案:

答案 0 :(得分:3)

基本上,GET请求将返回序列化为定义格式的资源,以及有关该资源的元数据(它们共同构成资源的表示)。当您返回表示时,它不需要包含元数据,也不需要与原始(或任何后续)GET请求的格式相同。然后,服务器将根据您提供的表示更新资源。

HTML中的一个示例是<head><body>元素,它们提供有关资源和资源表示的元数据;和text/htmlapplication/x-www-form-urlencoded内容类型,它们以两种不同的格式传输资源表示,前者使用元数据,后者没有。在POST之后获取资源时,您不希望收到application/x-www-form-urlencoded - 格式化数据!

我不确定“REST变体”是什么意思。只有一个REST。如果您指的是其他基于HTTP的API,请不要将它们称为REST。有关API样式的更多详细信息,请参阅Classification of HTTP-based APIs

最后,您要求提供非叶PUT请求的示例。我不确定你的意思是非叶子,因为我可以想到两种类型:

  1. 集合
  2. 子资源
  3. <强>集合 假设您有一个汽车目录,可在/cars获得。如果您决定要删除所有汽车,可以DELETE /cars/1DELETE /cars/2 ...等等,或者您可以选择PUT /cars空体或没有内容的数组。后者显然会更有效率。

    <强>子资源 继续这个主题,让我们说有一辆汽车,/cars/1由此表示:

    {
      "model":"Model-T",
      "mfgr":"Ford",
      "colour":"black"
    }
    

    现在,您可能希望允许这些字段通过/cars/1/mfgr等可以返回Ford{"mfgr":"Ford"}的网址进行访问。现在,URL /cars/1表示非叶资源。但是,在将新表示形式设置到URL时仍然没有问题。因此,这也会更新子资源URL的值。

    最后,您可能需要查看通过JSON传输超文本的HAL格式。

答案 1 :(得分:1)

您应该在媒体类型定义时使用“完整”表示。如果您正在设计自己的媒体类型,那么您的规范应该定义哪些部分是可变的,哪些部分是不可变的。例如,Shoji目录协议定义了旨在包含可变数据的a "body" member

  

通常,当存在正文成员时,处理器应该期待   身体内存在的价值可能是可变的(通过   例如,HTTP PUT或POST)并且应该期望外面的任何值   身体成员是不可改变的;也就是说,(可能)可写   插入但不更新。服务器是免费的,当然是允许或   禁止资源的任何部分的可变性。但是存在了   “身体”成员带有关于可变性的强烈暗示   该成员内外的数据。

这不是一个标准(虽然它对我来说显然是有用的,我希望它成为一个(眨眼))。请注意,服务器可以随意使用客户端发送的表示执行任何操作;任何HTTP服务器的最强要求是它试图执行客户端的意图(如果能够和允许)。它是如何以及在多大程度上确实是您特定应用的关注点,这就是为什么您没有找到任何关于它的规格。

在实践中,我没有发现服务器验证表示的链接或其他不可变部分是有用的;他们只是被忽略了。这可能导致客户决定他们可以省略这样的。同样,在实践中,我没有发现这是一个问题。