5

我被要求设计和实现一个 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 表示的典型资源时,其中大部分是逻辑上不能/不应该替换的数据。例如

{
 "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 期望客户端 PUT 整个资源、链接和所有内容,那么这可能就是我要做的。

支持 GET 和 PUT 的现实世界复杂非叶 REST 资源的一些示例,因此必须处理此问题,我们将不胜感激。当我搜索时,我得到了很多意见,还有很多例子展示了 GET 的工作原理。. . 但到目前为止,我还没有看到一个有据可查的例子,它显示了一个 PUT 到除了一个微不足道的叶子资源之外的任何东西(即一个不包含任何链接,除了可能是一个自我引用)。

4

2 回答 2

3

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

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

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

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

  1. 收藏品
  2. 子资源

集合 假设您有一个汽车目录,可在/cars. 如果您决定要擦除所有汽车,则可以执行DELETE /cars/1, DELETE /cars/2... 等等,或者您可以选择PUT /cars空主体或没有内容的数组。后者显然会更有效率。

子资源 继续这个主题,假设有一辆车,/cars/1它是这样表示的:

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

现在,您可能希望允许通过 URL 访问这些字段,例如/cars/1/mfgrwhich 将返回Ford或可能{"mfgr":"Ford"}. 现在 URL/cars/1代表一个非叶子资源。但是,将新的表示添加到 URL 中仍然没有问题。因此,这也会更新子资源 URL 的值。

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

于 2013-01-23T12:13:47.323 回答
1

您应该将“完整”表示作为您的媒体类型定义它。如果您正在设计自己的媒体类型,您的规范应该定义哪些部分是可变的,哪些是不可变的。例如,Shoji 目录协议定义了一个“body”成员,旨在包含可变数据:

一般来说,当一个主体成员存在时,处理器应该期望主体中存在的值可能是可变的(例如通过 HTTP PUT 或 POST),并且应该期望主体成员之外的任何值是不可变的;也就是说,(可能)在插入时可写,但在更新时不可写。服务器是免费的,当然可以允许或禁止资源的任何部分的可变性。但是“body”成员的存在强烈暗示了该成员内部和外部数据的可变性。

这不是一个标准(尽管它对我来说显然很有用,我希望它成为一个标准(眨眼))。请注意,服务器可以随意使用客户端发送的表示来做任何他们想做的事情。对任何 HTTP 服务器的最强要求是它尝试执行客户端的意图(如果能够并允许)。它如何以及在多大程度上确实是您的特定应用程序的一个问题,这就是为什么您在任何规范中都没有找到太多关于它的原因。

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

于 2013-01-22T20:08:14.687 回答