Http REST-修改资源的一部分-PUT或POST

Http REST-修改资源的一部分-PUT或POST,http,rest,http-headers,httpverbs,Http,Rest,Http Headers,Httpverbs,关于如何使用REST只更新资源的一部分(例如状态指示器),我看到了很多人在讨论这个问题 选择似乎是: 抱怨HTTP没有补丁或修改命令。然而,关于的公认答案很好地说明了为什么这不是一个看起来那么好的主意 使用带有参数的POST并识别方法(例如,名为“action”的参数)。一些建议是使用自定义方法名称指定X-HTTP-Method-Override头。这似乎导致了在实现中根据您试图做的事情进行切换的丑陋性,并且对不是一种特别安静的POST使用方式的批评持开放态度。事实上,采用这种方法开始感觉像RP

关于如何使用REST只更新资源的一部分(例如状态指示器),我看到了很多人在讨论这个问题

选择似乎是:

  • 抱怨HTTP没有补丁或修改命令。然而,关于的公认答案很好地说明了为什么这不是一个看起来那么好的主意

  • 使用带有参数的POST并识别方法(例如,名为“action”的参数)。一些建议是使用自定义方法名称指定X-HTTP-Method-Override头。这似乎导致了在实现中根据您试图做的事情进行切换的丑陋性,并且对不是一种特别安静的POST使用方式的批评持开放态度。事实上,采用这种方法开始感觉像RPC类型的接口

  • 使用PUT覆盖表示要更新的特定属性的资源的子资源。事实上,这实际上是子资源的过度使用,这似乎符合PUT的精神

  • 在这一点上,我认为#3是最合理的选择


    这是最佳实践还是反模式?还有其他选项吗?

    查看状态更新有两种方法

  • 更新一件事。那是一个推杆。选择3

  • 在事件的历史记录中添加额外的日志条目。此日志条目序列中的列表项是当前状态。那是一个帖子。备选案文2

  • 如果您是数据仓库或函数式编程类型的人,您往往不信任状态更改,并且喜欢将新的历史事实发布到一个静态的、不变的东西上。这确实需要区分事物与事物的历史;通向两张桌子

    否则,您不介意通过“更新”来改变某个事物的状态,并且您对PUT感到满意。这并不区分事物和它的历史,而是将所有内容放在一张表中

    就个人而言,我发现我越来越不信任可变对象和PUT(除了“错误更正”)。(即使如此,我认为旧的东西也可以保留,新的东西可以参照以前的版本添加。)

    如果状态发生了变化,我认为应该有一个状态日志或历史记录,并且应该有一个帖子向该历史记录中添加一个新条目。可能会有一些优化来反映此应用对象中的“当前”状态,但这只是幕后优化。

    选项3(放置到某个单独的子资源中)是您目前的最佳选择,它不一定是“错误的”只在主要资源本身上使用POST——尽管你可能不同意,这取决于你对它有多学究气

    坚持使用3并使用更细粒度的子资源,如果您确实需要类似补丁的行为,请使用POST。就我个人而言,即使补丁确实最终成为一个可行的选项,我仍然会使用这种方法。

    HTTP确实有一个补丁命令。它在中定义,并在中更新,目前正在等待。

    可以在不可用的地方发布和模拟修补程序
    在解释这一点之前,可能值得一提的是,使用POST进行常规更新并没有什么错(请参阅):

    POST只有在其他方法非常适合的情况下使用时才会成为问题:例如,检索应该是某个资源表示形式的信息(GET),完全替换表示形式(PUT)

    实际上,我们应该使用补丁对复杂的资源进行小的更新,但它并不像我们希望的那样广泛可用。我们可以使用附加属性作为POST的一部分来模拟补丁


    我们的服务需要对SAP、Flex、Silverlight、Excel等第三方产品开放。这意味着我们必须使用最低公分母技术——有一段时间我们无法使用PUT,因为所有客户端技术都只支持GET和POST

    我采用的方法是将“\u method=patch”作为POST请求的一部分。好处是,

    (a) 在服务器端很容易处理-我们基本上是假装补丁可用

    (b) 它向第三方表明,我们并没有违反REST,而是绕过了浏览器的限制。这也与几年前Rails社区处理PUT的方式一致,因此许多人应该能够理解

    (c) 当补丁变得更广泛可用时,它很容易更换

    (d) 这是对一个棘手问题的务实回应。

    补丁适用于补丁或差异格式。在那之前,它一点用处都没有

    对于使用自定义方法的解决方案2,无论是在请求中还是在头中,都是如此,不,不,这太糟糕了:)

    只有两种方法是有效的,要么放入整个资源,修改子数据,要么发布到该资源,要么放入子资源


    <>这取决于资源的粒度和缓存的预期结果。

    有点晚,但我会考虑使用这样的场景。

    在其核心,它需要资源的两个副本(原始副本和修改副本),并对其执行diff。diff的结果是一系列描述差异的补丁操作

    例如:

    [
      { "op": "replace", "path": "/baz", "value": "boo" },
      { "op": "add", "path": "/hello", "value": ["world"] },
      { "op": "remove", "path": "/foo" }
    ]
    

    有很多方法可以在generata中完成繁重的工作

    在实践中,最好暂时坚持使用POST,或者只是将您的资源拆分为子资源并应用到这些子资源中。缺少工具是否是一个问题当然取决于您拥有的工具,对吗?所以我建议尝试,而不是事先放弃这个选项。补丁解决了一个小问题,这个问题已经可以通过POST和一些常识来解决了——几乎可以肯定它会被滥用和破坏