REST:PUT 端点是不是应该在更新之前比较 GET 响应?

Posted

技术标签:

【中文标题】REST:PUT 端点是不是应该在更新之前比较 GET 响应?【英文标题】:REST: Should PUT endpoint compare the GET response before updating?REST:PUT 端点是否应该在更新之前比较 GET 响应? 【发布时间】:2019-02-23 01:07:39 【问题描述】:

我正在 Spring Boot 中开发一个 REST API,我正在尝试理解 PUT 操作。目前,我的 PUT 操作采用对象 ID 并检查对象是否存在,然后用新对象替换该对象。我有以下问题。

    我是否应该在保存新对象之前将旧对象与新对象进行比较,以了解新对象是否被修改并在对象未更改时返回适当的 http 响应状态? 如果我确实想比较,了解对象是否真的被修改的最佳方法是什么

谢谢。

【问题讨论】:

【参考方案1】:

不,您不需要进行一般比较。 PUT 意味着您需要用新值替换所有值,但如果您需要保留 created by 或 created time 属性,您应该从 db 获取记录并将必要值从以前的记录更新为新记录。

如果你需要比较两个对象,你需要重写 equal 和 hashCode 方法。然后您可以检查 a.equal(b) 以检查值是否已更改。请记住,如果对象包含数据时间或随机生成数,请避免将它们添加到 equal 方法中。

PATCH 是您需要从 db 获取当前记录并更新相关值的地方。

【讨论】:

【参考方案2】:

REST:PUT 端点是否应该在更新之前比较 GET 响应?

REST 和 HTTP 都没有对实现施加任何特定约束——只有语义受到约束。 RFC 7231

HTTP 没有准确定义 PUT 方法如何影响源服务器的状态,超出了用户代理请求的意图和源服务器响应的语义所能表达的范围......一般来说,所有实现细节资源接口后面被服务器故意隐藏了。

RFC 7232 可能知道您在寻找什么

如果收到的 If-Match 条件评估为 false,则源服务器不得执行请求的方法;相反,如果源服务器已验证正在请求状态更改并且最终状态已经是,则源服务器必须响应 a) 412(前提条件失败)状态代码或 b)2xx(成功)状态代码之一反映在目标资源的当前状态(即,用户代理请求的更改已经成功,但用户代理可能不知道它,可能是因为先前的响应丢失或其他人进行了兼容的更改用户代理)。

因此,就规范而言,您可以假装您更改了内容,即使无操作等同于客户要求的内容。

如果我确实想比较,了解对象是否真的被修改的最佳方法是什么

提供的信息不足。这将取决于诸如原始服务器如何存储资源状态之类的事情。如果您只是在处理原始文档,那么比较两个长哈希键就可以了。

【讨论】:

【参考方案3】:

您可以在 PUT 或 PATCH 之间做出选择,并非所有协议都支持 PATCH。

当客户需要完全替换现有资源时,他们可以 使用 PUT。当他们进行部分更新时,他们可以使用 HTTP PATCH。

如果您在此处使用 PUT,则需要进行所有比较并检查例如:

    从数据库中获取对象

    检查并更新任何更新的业务对象

    然后保存。 要回答您的问题,修改对象不需要您比较现有对象和新对象的值。

但如果客户端可以只发送更新的属性,那么使用 PATCH 会更好。

要了解更多信息以及如何实施,请写博客

HTTP PUT vs HTTP PATCH in a REST API

【讨论】:

以上是关于REST:PUT 端点是不是应该在更新之前比较 GET 响应?的主要内容,如果未能解决你的问题,请参考以下文章

REST - 端点是不是应该包含摘要数据?

通过 REST (PUT/POST) 更新资源

REST 端点中的多个 ID

REST API PATCH或PUT

验证 REST 端点上的字段

REST API 设计 - 最佳实践:链接现有子资源 [关闭]