【问题标题】:Restfull API with only PATCH requests instead of PUT for better extensibility?Restful API 只有 PATCH 请求而不是 PUT 以获得更好的可扩展性?
【发布时间】:2017-06-07 00:22:43
【问题描述】:

当大多数资源需要根据许多用例使用一组特定字段进行全部或部分更新时,我们正在开发一种 API。我们计划仅使用补丁请求进行更新,因为它提供了更大的灵活性(如果字段存在则更新,否则忽略)。为同一资源的整个更新创建 PUT 路由和为部分更新创建 PATCH 路由似乎是多余的,因为 PATCH 可以根据请求的字段同时执行这两种操作。这是一个不错的选择吗?除了验证字段存在之外,使用 PUT 而不是 PATCH 有什么好处?如果 PATCH 可以完成部分更新,为什么不到处使用 PATCH 呢?

【问题讨论】:

    标签: rest api django-rest-framework patch put


    【解决方案1】:

    我认为建议 PATCH 完全取代 PUT 并不公平。

    首先,您已经了解了 PUT 比 PATCH 更受欢迎的历史原因 - 它首先被实施。 RFC5789 提议 PATCH 于 2010 年发布,PUT 自 90 年代后期以来一直存在。因此,PUT 更有可能在大多数基础设施(客户端和服务器)上被广泛接受。如果您想要做的事情很容易被 PUT 描述,那么 PUT 只是一个更好的选择,因为它更有可能可用并正确实施。当然,这个问题的相关性一直在下降。

    除了您选择使用 PUT 而不是 PATCH 的原因之外。

    • PUT 被定义为幂等操作,而 PATCH 不是,在一般情况下也不能。因此,如果由于某种原因,您的客户通过 PUT 重新发布了文档,那么问题就不会像 PATCH 请求被应用两次那样大。
    • PUT 操作的文档格式被很好地定义为资源的修改表示 - 从广义上讲,PUT 与 GET 对称(尽管在某些情况下存在例外情况,例如用户无法修改的字段)。补丁不是。它对潜在的不同内容类型(例如差异样式)进行操作。完全不清楚 PATCH 文档的语义应该是什么,并且高度依赖于实现。如果您有一个基于 JSON 的资源并且想要将一个元素添加到数组中怎么办?您是否需要包含整个新数组的 JSON 文档?只是新的价值?如何从 JSON 文档中删除元素?也许您需要使用 diff 样式的格式 - 哦,对于简单的更改,这变得越来越复杂。是否曾尝试在半夜阅读差异来找出问题所在?
    • PUT 为 HATEOAS 应用程序在想要修改资源时应该如何工作提供了一个很好的模型 - 读取资源的现有状态,以某种方式对其进行更改,然后将更新后的状态发送回服务器。您可以使用 PATCH 对此进行建模,但实际上工作量更大 - 您必须读取现有状态,收集所有更改,然后将它们格式化为新格式。在服务器端,您必须以某种方式将所有这些更改应用于资源。比使用 PUT 复杂得多。
    • 从客户的角度来看,当您进行部分更新与完全更新时,您可能会尝试做不同的事情。部分更新可能因特定原因而发生,将它们建模为不同的操作并让服务器隐藏混乱的实现细节是有意义的。

    总而言之,PATCH 与 PUT 相比的主要优势在于其更大的灵活性,但这种灵活性是以复杂性为代价的。不再清楚请求是否是幂等的(它依赖于实现)。发生的更新不再可验证为 new 状态,它们必须以某种方式进行处理 - 因此资源的更新状态现在是旧状态和补丁的某些功能以获得新状态状态。但是,如果您的所有更新都是通过 PATCH 进行的,那么只有知道 原始 状态(或快照)所有后续补丁 ,您才能确定新状态以及它们被应用的顺序(基本上是期刊)。相比之下,PUT 提供了一个简单的保证 - 如果您 PUT 一个文档并获得成功 (2xx) 响应代码,那么该文档代表(或应该代表)资源的新状态。这种属性可以让您更轻松地推理您的应用程序,并且当您在凌晨 3 点调查问题时,这种东西可以真正提供帮助。

    不过,也许要问的问题是,拥有许多需要 PATCH 增加的灵活性(复杂性)的资源是否完全是 ReSTful?您的资源现在是否过于粗粒度,无法满足客户希望实现的各种更改?是否值得将大的资源分解为单独的资源,每个资源都使客户能够选择他们实际需要执行的更新类型?您的资源是否实际上聚集了不同类型的事物,通过不同的 URI 结构更好地建模?

    当然,PATCH 旨在解决特定问题 - 部分更新 - 它做得很好。如果您有真正需要支持部分更新的资源,那么您应该查看 PATCH。但我不建议过度使用 PATCH 进行所有更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-01
      • 1970-01-01
      相关资源
      最近更新 更多