我了解在 REST 中,PUT 操作完全更新服务器上的对象/记录。似乎一个常见的问题是如下场景:
似乎应该有一个标准的做法来拒绝步骤 4 中的 PUT 调用,方法是指示 PUT 请求正在更新对象的陈旧版本。这可以通过在“GET”操作期间在接收到的对象上包含时间戳或版本来完成。 (时间戳或版本只需要指示服务器提供的最后编辑版本 - 例如,指示检索时间的时间戳将打破幂等规则。客户端永远不会更新此时间戳/版本也很重要PUT 调用,否则 Bob 仍然可以不公正地覆盖 Alice 的文档。)
但是提供对象的版本似乎并不是 GET/PUT REST 调用的标准做法。忽略像这样的潜在冲突实际上是 REST 中的常见做法,还是有一种既定的模式来确保 Bob 不会不公正地拒绝和覆盖 Alice 的文档?
谢谢!
编辑:答案是在 RFC 9110 中。基本上第 4 步可以通过使用“If-Match”标头字段或类似字段来保护:
If-Match 最常与状态更改方法(例如,POST、PUT、DELETE)一起使用,以防止多个用户代理可能在同一资源上并行操作时意外覆盖(即,防止“丢失更新”问题).通常,如果所选表示的当前实体标签不是 If-Match 字段值中的成员,它可以与涉及选择或修改表示的任何方法一起使用以中止请求。
此外,对于我们这些使用 Spring 的人来说,可以添加一个简单的注释来自动支持 If-Match 验证:
https://docs.spring.io/spring-data/rest/docs/current/reference/html/#conditional.etag
似乎应该有一个标准的做法来拒绝步骤 4 中的 PUT 调用,通过指示 PUT 请求正在更新对象的陈旧版本。
好消息:我们有一个。
它显示为两个部分;在包含我们资源表示的响应中,我们包括特定于表示的验证器字段。
在修改资源的请求中,我们使用 条件请求 - 我们在请求中使用标准化字段(也称为标头)来标识我们试图替换的版本。
根据资源的当前状态,服务器然后要么正常处理请求,要么返回 412 Precondition Failed 响应。