PUT 是否应该始终能够插入?
Should PUT always be able to insert?
场景:
- 正在尝试创建 RESTful 网站 API(完全合规)
- 一个 PUT 请求被发送到
/person/123
(我的意图是更新)
- 资源
/person/123
不存在
疑问与分疑问:
我是否应该始终允许客户端保存(放置)资源,即使它不存在(即在数据库中)?
可能性:
不行,这种情况下限制客户端保存动作比较合适。
- 那么,哪个状态码适合响应 (400, 404)?
是的。 API 必须允许客户端使用 PUT 保存。
- 那么,我应该如何处理 Bob 在 Alice 删除相同资源后立即保存一些更改的可能性?
您可以选择两者之一。如果选择前者,那么404比较合适
在开始 PUT 之前,让我们先看看 PUT 与 POST 的不同之处。
对 POST 的期望是 non-idempotent。这意味着使用完全相同的数据 多次调用 POST 可能会 导致与只调用一次不同的服务器状态。
对 PUT 的期望是它是幂等的。这意味着使用完全相同的数据多次调用 PUT 不应 导致与只调用一次不同的服务器状态。
让我们看几个例子:
POST 例子
假设一个 POST 请求被发送到 /person/add
,其中包含一些数据以填充要添加的新人。第一次调用后,服务器将具有:
[
{ person: 0, ...data... }
]
(JSON 为简化示例而使用的语法)
现在,想象一下 完全相同的请求 再发生一三次:
[
{ person: 0, ...data... },
{ person: 1, ...data... },
{ person: 2, ...data... },
{ person: 3, ...data... }
]
在这个例子中,POST是非幂等的,同样的请求导致不同的服务器状态。
PUT 示例
现在假设一个 PUT 请求被发送到 /person/123
,其中包含一些数据以更新 ID 为 123
的人。第一次调用后服务器可能有:
[
{ person: 0, ...data... },
...
{ person: 123, ...updated data... }
]
现在,想象一下 完全相同的请求 再发生一三次:
[
{ person: 0, ...data... },
...
{ person: 123, ...updated data... }
]
在此示例中,PUT 是幂等的,相同的请求会导致相同的服务器状态。
那么当这个人不存在时呢?
嗯,有两个选择:
- 使用给定的 ID 创建
person
并填充其数据
- return 404,因为找不到给定的用户
让我们看看处理请求的不同之处
创建人物
初始服务器状态:
[
{ person: 0, ...data... }
]
PUT /person/123 {...new data...}
之后:
[
{ person: 0, ...data... },
{ person: 123, ...new data... }
]
多次PUT /person/123 {...new data...}
后:
[
{ person: 0, ...data... },
{ person: 123, ...new data... }
]
此示例表明,当您从数据创建 person
时,这里对服务器状态没有真正的危害。
404 错误
初始服务器状态:
[
{ person: 0, ...data... }
]
PUT /person/123 {...new data...}
之后:
[
{ person: 0, ...data... }
]
多次PUT /person/123 {...new data...}
后:
[
{ person: 0, ...data... }
]
这个例子 也 表明,如果 person
不存在,当您发送错误时,对服务器状态没有真正的损害。
那么这一切意味着什么?
REST 不是必须严格遵守的严格定义的规范。它更像是 set of guidelines.
这意味着一切由您决定。
如果可以安全地从 PUT 请求创建新数据集并简化您的程序,那么允许它发生并没有什么害处,只要您执行所有与您希望的相同的验证和错误处理正在处理 POST 创建新对象的请求。
如果从 PUT 请求创建新数据集非常困难或无法安全地完成——例如当只有 一些 数据被更新时,并且服务器不能创建一个完整的对象——那么无论如何都不允许它并且return适当的错误代码(404 Not Found)。
场景:
- 正在尝试创建 RESTful 网站 API(完全合规)
- 一个 PUT 请求被发送到
/person/123
(我的意图是更新) - 资源
/person/123
不存在
疑问与分疑问:
我是否应该始终允许客户端保存(放置)资源,即使它不存在(即在数据库中)?
可能性:
不行,这种情况下限制客户端保存动作比较合适。
- 那么,哪个状态码适合响应 (400, 404)?
是的。 API 必须允许客户端使用 PUT 保存。
- 那么,我应该如何处理 Bob 在 Alice 删除相同资源后立即保存一些更改的可能性?
您可以选择两者之一。如果选择前者,那么404比较合适
在开始 PUT 之前,让我们先看看 PUT 与 POST 的不同之处。
对 POST 的期望是 non-idempotent。这意味着使用完全相同的数据 多次调用 POST 可能会 导致与只调用一次不同的服务器状态。
对 PUT 的期望是它是幂等的。这意味着使用完全相同的数据多次调用 PUT 不应 导致与只调用一次不同的服务器状态。
让我们看几个例子:
POST 例子
假设一个 POST 请求被发送到 /person/add
,其中包含一些数据以填充要添加的新人。第一次调用后,服务器将具有:
[
{ person: 0, ...data... }
]
(JSON 为简化示例而使用的语法)
现在,想象一下 完全相同的请求 再发生一三次:
[
{ person: 0, ...data... },
{ person: 1, ...data... },
{ person: 2, ...data... },
{ person: 3, ...data... }
]
在这个例子中,POST是非幂等的,同样的请求导致不同的服务器状态。
PUT 示例
现在假设一个 PUT 请求被发送到 /person/123
,其中包含一些数据以更新 ID 为 123
的人。第一次调用后服务器可能有:
[
{ person: 0, ...data... },
...
{ person: 123, ...updated data... }
]
现在,想象一下 完全相同的请求 再发生一三次:
[
{ person: 0, ...data... },
...
{ person: 123, ...updated data... }
]
在此示例中,PUT 是幂等的,相同的请求会导致相同的服务器状态。
那么当这个人不存在时呢?
嗯,有两个选择:
- 使用给定的 ID 创建
person
并填充其数据 - return 404,因为找不到给定的用户
让我们看看处理请求的不同之处
创建人物
初始服务器状态:
[
{ person: 0, ...data... }
]
PUT /person/123 {...new data...}
之后:
[
{ person: 0, ...data... },
{ person: 123, ...new data... }
]
多次PUT /person/123 {...new data...}
后:
[
{ person: 0, ...data... },
{ person: 123, ...new data... }
]
此示例表明,当您从数据创建 person
时,这里对服务器状态没有真正的危害。
404 错误
初始服务器状态:
[
{ person: 0, ...data... }
]
PUT /person/123 {...new data...}
之后:
[
{ person: 0, ...data... }
]
多次PUT /person/123 {...new data...}
后:
[
{ person: 0, ...data... }
]
这个例子 也 表明,如果 person
不存在,当您发送错误时,对服务器状态没有真正的损害。
那么这一切意味着什么?
REST 不是必须严格遵守的严格定义的规范。它更像是 set of guidelines.
这意味着一切由您决定。
如果可以安全地从 PUT 请求创建新数据集并简化您的程序,那么允许它发生并没有什么害处,只要您执行所有与您希望的相同的验证和错误处理正在处理 POST 创建新对象的请求。
如果从 PUT 请求创建新数据集非常困难或无法安全地完成——例如当只有 一些 数据被更新时,并且服务器不能创建一个完整的对象——那么无论如何都不允许它并且return适当的错误代码(404 Not Found)。