使用 PUT 和 POST 更新 REST 资源

Update REST resource using PUT and POST

我很难理解 REST 更新资源的原则。

例如,此响应包含资源的 ID

获取/users/5 { "user_id": 5 "first_name" : "John", "last_name" : "Doe", "minutes_active": 10

} 这假设资源的 id 是在请求​​的 url 中声明的

GET /users/5
{
"first_name" : "John",
"last_name" : "Doe",
"address": 
{
"street" : "First Street 10",
"postal" : "0000",
"city": "Dublin"
},
"phones": [
{
"type" : "work",
"number" : "555 473-0000",
},
{
"type" : "home",
"number" : "555 473-0000",
}]
}

如果我只想更新地址,我正在考虑使用以下选项之一。

1.
POST /users/5
{
"address": 
{
"street" : "First Street 10",
"postal" : "0000",
"city": "Dublin"
}
}

2.
PUT /users/5
{
"address": 
{
"street" : "First Street 10",
"postal" : "0000",
"city": "Dublin"
}
}

3.
PUT /users/5/address
{
"address": 
{
"street" : "First Street 10",
"postal" : "0000",
"city": "Dublin"
}
}

虽然 POST 不是幂等的,但在这种情况下它总是做同样的工作(作为幂等),就像 PUT 一样。我在某处读到这种类型的请求被认为是部分更新,对于这种类型的请求我们应该使用 PATCH。

此时我想避免 PATCH,并使用一些替代方法。

此外,如果我将地址作为单独的资源隔离在 /users/5/address 中,我可以使用 PUT,这将是一个完全遵循 REST 原则的解决方案。但这可能是我开发人员想要更新 fe 的问题。电话和地址都使用一个请求。

如果我真的想使用选项 1 或 2(一些大型系统,如 zendesk、twitter 正在这样做),我是否会遇到我目前没有真正看到的任何严重问题?

REST 答案是:您将如何处理网站?

您将获取用户配置文件的当前表示,并包含该表示将是 links 的数量,以及提示代理的语义提示(你),至于每个 link 是做什么用的。您知道您的目标是更改地址,将遵循 GET link,检索包含表单的表示,其中包含一堆字段和 link 指示客户如何提交表单.因此,您将提交表单:数据的表示形式将被发送 (POST) 到某个资源,该资源又会与域通信以产生您想要的副作用。

或...

您将获取用户配置文件的当前表示,并包含该表示将是 links 的数量,以及提示代理的语义提示(你),至于每个 link 是做什么用的。你,知道你的目标是改变地址,会遵循 link 的 GET,检索表示 地址,您将在您最喜欢的文本编辑器中对其进行更新。然后您将新表示放回相同的资源,这会更新地址文档的服务器副本。

因此,“REST 原则”并不关心您是否使用 POST or PUT——只要您以与 RFC 一致的方式使用它们即可。 REST 非常关心这样一个事实,即您对所有资源使用相同的 POST 和 PUT 方式,并且您发送给客户端的表示指示客户端的行为(而不是在一组自定义响应中编程)。

Furthermore, if I isolate address as a separate resource in /users/5/address i could use PUT and it would be a solution that fully follows REST principles. But this could be a problem I a developer want to update fe. both phones and addresses using a single request.

这不是问题 - 它有两个不同的答案。

一种可能是您始终将 phone 包含在地址中,让代理决定要进行的更改。

但“高级”答案是您有两种不同的资源——一种用于编辑地址,另一种用于同时编辑地址和 phone 号码。 HTTP 资源是关于您的域与其消费者之间的集成协议;如果你想引入一个新的协议,你只需实现一个新的资源家族来支持它,然后添加 links 来宣传它的存在。

GET /changeOfAddressForm?user=5

GET /changeContactDetailsForm?user=5