【问题标题】:Including Id in URI for PUT requests在 PUT 请求的 URI 中包含 Id
【发布时间】:2012-02-13 17:46:02
【问题描述】:

我正在阅读一些关于使用休息服务适当使用 URI 的文档,并且遇到了一个基本 GET .. DELETE 请求的示例。

示例 uri 是:

获取所有用户

GET http://mydomain.org/api/users

获取特定用户

GET http://mydomain.org/api/users/1

更新用户

PUT http://mydomain.org/api/users/1

删除用户

DELETE http://mydomain.org/api/users/1

用户资源可以是 JSON 或 XML,格式为:

{
    Id: 1,
    FirstName: 'John',
    LastName: 'Doe'
}

我的问题是这样的。为了维护 REST 原则,是否需要在 PUT 请求的 URI 中包含资源的 id?

【问题讨论】:

    标签: rest


    【解决方案1】:

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

    您希望将资源 PUT 指向您打算从其 GET 的同一 URI。

    RFC 72314.3.4 PUT

    【讨论】:

    • 这是有道理的。我的假设是 id 将始终与资源一起提供,但我想情况并非总是如此。
    • 事实上,如果您开始在界面中使用 URI,您可能很快就会发现从资源表示本身中删除 id 很有用。
    • RFC-2616 已被 RFC-7231 废弃
    • @prasanthv 你是什么意思,PUT 有什么变化吗?我不这么认为。
    【解决方案2】:

    我本来想问一个类似的问题,但我想我找到了答案。我不确定这是否符合 REST 原则,但这就是为什么不将 ID 包含在 URI 中的原因。 所以说你的PUT 就像:

    PUT http://mydomain.org/api/users
    

    然后您碰巧更新了具有不同 ID 但相同 URI 的多个用户,因为您的 URI 中没有 ID。然后,这里要知道的重要一点是 PUT 是幂等的 http 动词。这意味着调用它一次应该与调用它多次具有相同的效果。因此,网络中的某些中间节点,仅仅遵循您多次 PUT 的事实,可能会忽略除一个请求之外的所有请求,因为它们具有相同的 URI。最后,这绝对不是您想要的,因为其目的是更新多个用户,而不仅仅是一个。

    【讨论】:

    • 我怀疑这是可能的,因为身体会有所不同。即使您正在更新同一个资源,您也可以对其进行不同的更新(具有不同的值),而忽略其中一些是一种非常出乎意料的行为。
    • 幂等动词无论被调用多少次都应该具有相同的效果。这是标准规定的。
    • Огњен Шобајић,只有在请求完全相同的情况下才会如此。假设我们有两个请求PUT: /api/users/1,正文为{"name":"Foo"}{"name":"Bar"}。幂等并不意味着第二个请求会被忽略,对吧?这只是意味着执行完全相同的请求与只执行一次具有相同的效果。
    • “幂等动词并不意味着第二个请求会被忽略”——是的,这是正确的。但它可能!它在网络中的中间节点上决定它是否要通过具有相同 URI 的第二个 PUT 请求。 HTTP 标准允许在某些情况下(例如交通拥堵)忽略具有相同 URI 的先前请求。我认为重要的是 URI,而不是带有正文的整个请求。
    • 我认为这是非常好的arctile。它适合单个屏幕dzone.com/articles/rest-api-path-vs-request-body-parameters
    【解决方案3】:

    PUT http://example.com/api/users + body 的行为类似于带有键 http://example.com/api/users 和值主体的映射的放置。如果不存在则创建一个新条目,否则覆盖现有条目。

    问题http://example.com/api/users 背后的资源是什么?

    答案:和GET http://example.com/api/users提供的一样,所有用户列表

    因此,PUT http://example.com/api/users 命令意味着您将所有用户列表替换为您提供的用户列表。

    为保持一致性,正文应包含用户数组:

    [
      {
        Id: 1,
        FirstName: 'John',
        LastName: 'Doe'
      },
      {
        Id: 2,
        FirstName: 'Albert',
        LastName: 'Einstein'
      }
    ]
    

    【讨论】:

    • 我认为这是 API 设计的一个很好的例子。这可能不是我在公共 API 中允许的,因为一次更新这么多资源可能很危险,但感谢您的示例。
    【解决方案4】:

    在放置请求的 URL 中包含 id 的另一个好处是 CREATE/UPDATE 函数可以共享一些逻辑。

    假设您有一个包含 3 列的用户表。

    id(primary key, auto increment) | name | age
    

    创建用户会生成一个 ID。

    POST /users
    {
      name: "foo"
      age: 25
    }
    -> generate id 123
    

    由于 id 在 URL 中,您可以使用相同的请求正文结构来更新用户。

    PUT /users/123
    {
      name: "bar"
      age: 25
    }
    

    这可能与 REST 主体关系不大,但它可以根据您的语言/框架在实践中简化请求处理的代码。

    【讨论】:

      猜你喜欢
      • 2017-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-21
      • 1970-01-01
      • 2021-04-20
      相关资源
      最近更新 更多