无法理解一些基本的REST东西

时间:2013-06-06 14:09:53

标签: api http rest

假设我的模型是:

用户:

  • ID
  • 昵称

我有一个集合/users/

我希望/users/{id}而非/users/${nickname}检索用户,因为在某些更复杂的情况下,可能没有“逻辑唯一约束”。

所以我可以使用的基本JSON有效负载例如:

{
  id: 123,
  nickname: 'someUserName'
}

这里没什么好看的。


POST / users /

据我所知,用户是一个标识符。它是资源表示的一部分,因此它应该在有效负载(?)中。

如果我想在后端自己生成ID,请使用数据库序列作为示例?

然后我的有效负载变为:

{
  nickname: 'someUserName'
}

这是否合适?

该POST的输出应该是什么?没有?只是引用资源位置的标题,包括ID?


获取/ users / id

当我们获取资源时,我们将其内容加载为JSON:

{
  id: 123,
  nickname: 'someUserName'
}

PUT on / users / id

据我所知,此方法使用的有效负载应该“覆盖”资源内容。如果我们想要部分更新,我们会使用PATCH。

但如果我这样做:

PUT /users/123

{
  id: 456,
  nickname: 'someUserName'
}

这是否意味着我们想要更新资源的ID?

在URI和有效负载中使用id不是多余的吗?


其实我真的不知道如何处理id

我不知道我是否应该在所有POST / PUT / DELETE操作中使用相同的资源表示。

我不知道id是否应该是唯一(?)资源表示的一部分。 但是如果id不是表示的一部分,那么当我列出用户时,使用GET /users/,如果没有返回id,那么我不知道客户端如何获取用户ID ...

有人能帮助我吗? :)

2 个答案:

答案 0 :(得分:5)

首先是 如果您不使用HATEOAS

,则不是REST

我希望你理解这一点,我会在最后回到那里。

在/ users / 上发布

POST

完全可以在POST有效负载中不使用ID。如果存在ID会出现错误消息,那么开发人员就会明白他们做错了 因此,如果您的用户资源中没有任何其他内容,则只有昵称作为有效负载才是完全有效的

服务器的输出应包括三个重要的事项:

  1. HEADER:表示成功或失败的状态代码(通常为201 Created
  2. HEADER:新创建的资源的位置(仅Location: /path/to/resource
  3. BODY:已创建资源的表示形式。像GET一样回馈完整的有效载荷!
  4. GET

    完全有效

    PUT

    您对PUT / PATCH的分析与规范相匹配,新资源应与有效负载相同,这意味着用户希望在不同时更改ID。如果有效负载包含不应更改的值(如ID),则有两种可能:

    1. 忽略有效负载中的ID
    2. 返回错误
    3. 在这两种情况下都会告知用户您的操作和出错的地方。我更喜欢发送/获得400 Bad Request。如果特权用户可以更改ID,但特定用户不能更改403 403 Forbidden。 还要确保记录您的API行为。您可以在API中省略ID。不要忘记以一致的方式处理POST有效负载中给出的ID!

      总体问题

      REST在资源上运行 / users /是资源集合的示例
      / users / {id}是单个资源的示例
      您应该始终在每个响应中使用完全相同的表示。如果由于某种原因,仅提供信息片段更适合添加指向完整资源表示的元数据(链接)。
      除了用户的第一个POST请求之外,ID始终存在。 POST意味着资源的未来位置未知,必须由服务器提供。 这也意味着GET / users /应该返回每个资源的ID。

      与API一样,返回严格并在请求中宽容。记录您的行为,以便用户可以学习。

      HATEOAS

      如果您实现HATEOAS(超媒体作为应用程序状态引擎),REST的真正美丽就会变为白昼。部分这意味着您应该使用有用的标记/链接组合来表示您的表示。这样客户就不再需要构建网址了。

      使用HAL进行用户表示的示例如下:

      {
          "_links:" {
              "self": { "href": "http://yourrest/users/123" }
          },
          "id": "123"
          "nickname": "someUserName"
      }
      

      使用HAL的一个很好的总结由Matthew Weier O'Phinney in his blog when he developed a ZF2 REST Module编写(第一个条目是完全免费的,只能解释HAL)。

答案 1 :(得分:0)

我正在解释您的描述,说id不是资源的一部分,它是资源的唯一标识符。在这种情况下,它不应该是任何操作的有效载荷的一部分。

带有有效负载POST /users

{"nickname": "somebody"}将创建一个新资源,并在Location标头中返回一个URL。该URL可能看起来像/users/123,但从客户的角度来看,没有理由期待这一点。它可能看起来像/something/else/entirely

GET /users/123会(假设早期POST返回的URL)返回有效负载{"nickname": "somebody"}

PUT /users/123(使用与上面相同的假设)将资源替换为您使用PUT发送的有效负载,例如{"nickname": "somebody else"}

如果您希望客户端能够命名资源,那么您还可以PUT /users/123使用该URL创建新资源。

我知道没有通用的RESTful方法来重命名资源。我认为使用旧URL作为查询部分或正文的一部分的POST是有意义的。

现在,假设我错了,你确实希望id成为资源本身的一部分。然后每个有效载荷都包含它。但从客户的角度来看,不应假设"id": 123暗示网址为/users/123

最后,所有这些都是从一个相当纯粹的观点来看。将URL视为资源的唯一真实标识符是有价值的,但是破坏该规则并让客户端使用逻辑来创建URL并不是很糟糕。