Restfull API只有PATCH请求而不是PUT才能获得更好的可扩展性?

时间:2017-01-22 11:26:57

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

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

1 个答案:

答案 0 :(得分:1)

我真的不认为建议PATCH完全取代PUT是公平的。

首先,您已经了解了PUT比PATCH更受欢迎的历史原因 - 首先实施了它。 RFC5789提出PATCH于2010年出版,PUT自90年代末开始出现。因此,在大多数基础设施(客户端和服务器)上,PUT更可能被广泛接受。如果您想要做的事情就像PUT一样容易描述,那么PUT只是一个更好的选择,因为它更可能是正确可用和实现的。当然,这个问题一直在减少相关性。

除此之外,你有理由选择使用PUT而不是PATCH。

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

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

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

当然,PATCH旨在解决一个特定问题 - 部分更新 - 并且它做得很好。如果您拥有真正需要支持部分更新的资源,那么您应该查看PATCH。但我不建议通过PATCH's进行全面更新。