仅使用补丁请求而不是PUT的Restfull API,以获得更好的扩展性?

仅使用补丁请求而不是PUT的Restfull API,以获得更好的扩展性?,rest,api,django-rest-framework,patch,put,Rest,Api,Django Rest Framework,Patch,Put,根据许多用例,当大多数资源需要全部或部分更新为一组特定字段时,我们正在开发一个API。我们计划只使用补丁请求进行更新,因为它在字段存在时提供了更大的灵活性。为同一资源创建整个更新的PUT路由和部分更新的补丁路由似乎是多余的,因为补丁可以根据请求的字段同时执行这两项操作。这是个好选择吗?除了验证字段是否存在外,使用PUT而不是PATCH有什么好处?如果补丁可以完成整个部分更新,为什么不到处使用补丁呢 我真的认为,建议补丁完全取代PUT是不公平的 首先,您已经了解了PUT比PATCH更受欢迎的历史原

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

我真的认为,建议补丁完全取代PUT是不公平的

首先,您已经了解了PUT比PATCH更受欢迎的历史原因——它是最先实现的。“建议补丁”于2010年发布,自90年代末开始发布。因此,PUT更可能在大多数基础架构(包括客户端和服务器)上被广泛接受。如果你想做的事情很容易用PUT来描述,那么PUT就是一个更好的选择,因为它更容易被使用和正确实现。当然,这个问题的相关性一直在下降

除此之外,您选择使用PUT而不是PATCH还有一些原因

PUT被定义为幂等运算,而PATCH不是,并且在一般情况下不能。因此,如果出于某种原因,您的客户机通过PUT重新发布文档,那么问题就不会像应用两次补丁请求那样严重。 PUT操作的文档格式定义为资源的修改表示形式——广义上讲,PUT与GET是对称的,尽管在某些情况下存在例外,例如用户不可修改的字段。补丁不是。它在一种可能不同的内容类型上运行,例如diff样式。补丁文档的语义应该是什么还不清楚,并且高度依赖于实现。如果您有一个基于JSON的资源,并且希望向数组中添加一个元素,该怎么办?您需要包含整个新数组的JSON文档吗?只是新的价值观?如何从JSON文档中删除元素?也许你需要使用一种不同风格的格式——哦,对于简单的更改来说,这变得越来越复杂了。有没有试过在半夜读一本书来弄清哪里出了问题? PUT为HATEOAS应用程序在需要修改资源时的工作方式提供了一个很好的模型—读取资源的现有状态,以某种方式进行更改,然后将更新后的状态发送回服务器。您可以使用补丁对此进行建模,但实际上需要更多的工作—您必须读取现有状态,收集所有更改,然后将它们格式化为新格式。在服务器端,您必须以某种方式将所有这些更改应用于资源。比看跌期权复杂得多。 从客户的角度来看,当您进行部分更新和完全更新时,您可能会尝试做不同的事情。部分更新可能是由于特定的原因而发生的,将它们建模为不同的操作并让服务器隐藏混乱的实现细节是有意义的。 总的来说,补丁比PUT的主要优势在于更大的灵活性,但这种灵活性是以复杂性为代价的。现在已经不清楚请求是否是幂等的,它依赖于实现。发生的更新不再作为新状态进行验证,它们必须以某种方式进行处理-因此,资源的更新状态现在是旧状态和补丁的函数,以获得新状态。但是,如果所有更新都是通过补丁进行的,那么只有知道原始状态或快照、所有后续补丁以及它们在日志中应用的顺序,才能确定新状态。相比之下,PUT提供了一个简单的保证——如果您放入一个文档并获得一个成功的2xx响应代码,那么该文档表示或应该表示资源的新状态。这种属性使您更容易对应用程序进行推理,当您在凌晨3点调查问题时,这种属性确实会有所帮助

不过,也许要问的问题是,拥有许多需要补丁增加灵活性和复杂性的资源是否完全是ReSTful的?对于您的客户希望实现的更改类型,您的资源现在是否过于粗粒度?是否值得将大型更新分解为单独的资源,每个资源都让客户机能够选择实际需要执行的更新类型?您的资源是否真的聚集了不同类型的东西,通过不同的URI结构对它们进行建模会更好

当然,这个补丁是为解决一个特定的问题而设计的——部分更新——而且它做得很好。你有真正需要的资源 支持部分更新的es,然后您应该查看修补程序。但我不建议过火,通过补丁进行所有更新