问题 如何更新REST资源集合


我有一个REST URI用于资源列表,例如:

http://foo.com/group/users

这些用户中的每一个都有一个序列号,我想公开一种方法,为集合中的所有用户重新编号这些值,并使访问列表的每个人都可以使用此更改。由于这是对整个集合的一个动作,我不知道如何实现这一点。

我可以设想一个像这样的URL http://foo.com/group/users?sequence=normalize 但不是 PUT 也不是 POST 除非我使用新数字作为消息数据提交整个集合,否则对整个列表确实有意义。

如何以RESTful方式更新整个集合,而无需重新发送集合中的所有更新资源?


9650
2018-02-20 20:58


起源



答案:


在raffian对我最初的回应发表评论之后,我将我的回答重新设计为更加RESTful ......

  • 使用该方法 PATCH

此方法通常旨在部分更新资源的状态。对于列表资源,我们可以发送一个列表,其中只包含要更新的元素和列表中元素的标识符。以下请求将是:

PATCH /group/users
[
    { "id": "userId1", "sequence": "newSequenceNumber1" },
    { "id": "userId2", "sequence": "newSequenceNumber2" },
    (...)
]
  • 使用该方法 POST 在列表资源上

此方法通常用于在资源管理的列表中添加元素。因此,如果您想利用它来执行此操作,我们需要在请求中传递有关要执行的操作的提示。我们可以选择在专用标头中或在有效负载内添加它。

随着 标题方法,你会有类似的东西:

POST /group/users
X-Action: renumbering
[
    { "id": "userId1", "sequence": "newSequenceNumber1" },
    { "id": "userId2", "sequence": "newSequenceNumber2" },
    (...)
]

随着 有效载荷方法,你会有类似的东西:

POST /group/users
{
    "action": "renumbering",
    "list": {
        [
            { "id": "userId1", "sequence": "newSequenceNumber1" },
            { "id": "userId2", "sequence": "newSequenceNumber2" },
            (...)
        ]
    }
}

希望它能帮到你, 蒂埃里


12
2018-02-22 13:54



这似乎是正确的方向,但如果请求不包括列表中的所有当前用户,我该如何处理?例如:用户A获取其中包含50个用户的列表,用户B将新用户添加到列表中,然后A在PATCH中发送重新编号的50,但它不考虑该新用户(反之亦然)用户被删除。)我担心在这种情况下,我们最终会得到两个重复的数字;有什么方法可以阻止这种情况吗? - Nick Gotch
我认为您应该考虑利用HTTP标头 ETag 和 If-Match 用REST实现optimitic锁定。此链接可能会让您感兴趣: looselyconnected.wordpress.com/2010/03/25/...。希望它能帮到你。 - Thierry Templier


答案:


在raffian对我最初的回应发表评论之后,我将我的回答重新设计为更加RESTful ......

  • 使用该方法 PATCH

此方法通常旨在部分更新资源的状态。对于列表资源,我们可以发送一个列表,其中只包含要更新的元素和列表中元素的标识符。以下请求将是:

PATCH /group/users
[
    { "id": "userId1", "sequence": "newSequenceNumber1" },
    { "id": "userId2", "sequence": "newSequenceNumber2" },
    (...)
]
  • 使用该方法 POST 在列表资源上

此方法通常用于在资源管理的列表中添加元素。因此,如果您想利用它来执行此操作,我们需要在请求中传递有关要执行的操作的提示。我们可以选择在专用标头中或在有效负载内添加它。

随着 标题方法,你会有类似的东西:

POST /group/users
X-Action: renumbering
[
    { "id": "userId1", "sequence": "newSequenceNumber1" },
    { "id": "userId2", "sequence": "newSequenceNumber2" },
    (...)
]

随着 有效载荷方法,你会有类似的东西:

POST /group/users
{
    "action": "renumbering",
    "list": {
        [
            { "id": "userId1", "sequence": "newSequenceNumber1" },
            { "id": "userId2", "sequence": "newSequenceNumber2" },
            (...)
        ]
    }
}

希望它能帮到你, 蒂埃里


12
2018-02-22 13:54



这似乎是正确的方向,但如果请求不包括列表中的所有当前用户,我该如何处理?例如:用户A获取其中包含50个用户的列表,用户B将新用户添加到列表中,然后A在PATCH中发送重新编号的50,但它不考虑该新用户(反之亦然)用户被删除。)我担心在这种情况下,我们最终会得到两个重复的数字;有什么方法可以阻止这种情况吗? - Nick Gotch
我认为您应该考虑利用HTTP标头 ETag 和 If-Match 用REST实现optimitic锁定。此链接可能会让您感兴趣: looselyconnected.wordpress.com/2010/03/25/...。希望它能帮到你。 - Thierry Templier


您可以在URI上同时使用PATCH和POST。如果我是你,我会使用PATCH。这是批量更新的最佳解决方案。


2
2018-02-22 18:08





从语义上讲, HTTP PATCH方法 是正确的方法。这也在描述中 目前选择的答案

PATCH /group/users

[
    { "id": "userId1", "sequence": "newSequenceNumber1" },
    { "id": "userId2", "sequence": "newSequenceNumber2" },
    ...
]

但是,所选答案中描述的第二种方法并不简单,因为您在POST请求中发明了新动词。这是SOAP,而不是REST。


1
2018-06-13 09:03