【问题标题】:Is REST DELETE really idempotent?REST DELETE 真的是幂等的吗?
【发布时间】:2011-05-04 13:16:33
【问题描述】:

DELETE 应该是幂等的。

如果我删除http://example.com/account/123,它将删除该帐户。

如果我再次执行此操作,我是否会收到 404,因为该帐户不再存在?如果我尝试删除一个从未存在过的帐户怎么办?

【问题讨论】:

  • 除了答案之外,我建议不要过多地关注幂等特性:它没有说明任何关于交换性和并发请求的内容。例如,同一个“R1”PUT 请求的 N+1 应该具有相同的效果,但是您不知道其他客户端是否在您的请求之间发出了不同的 PUT/DELETE “R2”请求,所以当 nR1= R1 和 mR2=R2,如果你只从单个客户端的角度来看,你得到交错的“R1”和“R2”请求的地方不一定“看起来”是幂等的。

标签: http rest http-headers


【解决方案1】:

假设我们必须管理由 id、name、city 表示的足球队。

{
    id: "1",
    name: "manchester united",
    city : "manchester "
}

说delete是幂等的意思是如果你多次调用DELETE /team/1系统的状态保持不变(其实是第一次调用DELETE /team/1删除团队。也就是说delete是幂等的,因为重复调用让系统状态不变。

同样我们可以说PUT 也是幂等的。 想象一下你不止一次做这个 PUT:

PUT /team/1
{
        id: "1",
        name: "liverpool",
        city : "liverpool"
}

此类 PUT 请求的重复调用始终具有相同的效果(第 1 队将是利物浦队)。

显然 GET 请求也是幂等的。

【讨论】:

    【解决方案2】:

    引用自我的another answer here

    从历史上看,1999 年发布的 RFC 2616 是引用最多的 HTTP 1.1 规范。不幸的是its description on idempotency was vague,这为所有这些辩论留下了空间。但该规范已被 RFC 7231 取代。引用自 RFC 7231, section 4.2.2 Idempotent Methods,强调我的:

    如果预期的 EFFECT ON,则请求方法被认为是“幂等的” 使用该方法的多个相同请求的服务器是 与单个此类请求的效果相同。的请求方法 本规范定义的 PUT、DELETE 和安全请求方法 是幂等的

    所以,它是写在规范中的,幂等性是关于对服务器的影响。第一个 DELETE 返回 204,然后随后的 DELETE 返回 404,这种不同的状态码不会使 DELETE 非幂等。使用这个论点来证明随后的 204 返回是完全不相关的。


    好的,所以这与幂等性无关。但是接下来可能会出现一个问题,如果我们在后续的DELETE中仍然选择使用204呢?好吗?

    好问题。动机是可以理解的:让客户端仍然达到预期的结果,而不用担心错误处理。我想说,在随后的 DELETE 中返回 204 是一个基本上无害的服务器端“善意的谎言”,客户端不会立即说出区别。这就是为什么有人在野外这样做并且它仍然有效。请记住,这样的谎言在语义上可能被认为是奇怪的,因为“GET / non-exist”返回 404,但“DELETE /non-exist”返回 204,此时客户端会发现您的服务不完全符合section 6.5.4 404 Not Found.

    但是,RFC 7231 暗示的预期方式,即在随后的 DELETE 中返回 404,首先应该不是问题。更多的开发人员选择这样做。这大概是因为,任何实现 HTTP DELETE(或任何 HTTP 方法,就此而言)的客户端都不会盲目地假设结果总是成功 2xx。然后,一旦开发人员开始考虑错误处理,404 Not Found 将是首先想到的错误之一。那时,他/她希望得出一个结论,即 HTTP DELETE 操作忽略 404 错误在语义上是安全的。问题解决了。

    【讨论】:

      【解决方案3】:

      是的。无论响应代码如何。

      来自latest RFC for HTTP 1.1(强调我的):

      区分幂等方法是因为请求可以是 如果在通信失败之前发生自动重复 客户端能够读取服务器的响应。例如,如果一个 客户端发送 PUT 请求并关闭底层连接 在收到任何响应之前,客户端可以建立一个新的 连接并重试幂等请求。它知道重复 该请求将具有相同的预期效果,即使原来的 请求成功,虽然响应可能不同。

      它明确表示响应可能不同。更重要的是,它指出了这个概念的由来:如果一个动作是幂等的,那么客户端在遇到任何错误时都可以重复该动作,并且知道这样做不会导致任何崩溃;如果没有,客户端将不得不进行额外的查询(可能是GET)以查看前一个是否有效,然后才能安全地重复操作。只要服务器能做出这样的保证,动作就是幂等的。引用another comment:

      计算幂等性是关于系统的健壮性。由于事情可能会失败(例如网络中断),当检测到故障时,您如何恢复?最简单的恢复是再做一次,但这只有在再做一次是幂等的情况下才有效。例如。 discard(x) 是幂等的,但 pop() 不是。都是关于错误恢复的。

      【讨论】:

        【解决方案4】:

        重要的区别是幂等是指副作用,而不是所有-效果或响应。如果您执行DELETE http://example.com/account/123,则效果是帐户 123 现在已从服务器中删除。这是唯一的效果,唯一的更改到服务器的状态。现在假设您再次执行相同的DELETE http://example.com/account/123 请求,服务器将响应不同,但其状态是相同的。

        它不像 DELETE 请求决定以不同的方式更改服务器状态,因为该帐户丢失,例如删除另一个帐户或留下错误日志。不,您可以调用同一个 DELETE 请求一百万次,并且可以确保服务器处于与您第一次调用它时相同的状态

        【讨论】:

          【解决方案5】:

          幂等是指请求完成后系统的状态


          在所有情况下(除了错误问题 - 见下文),该帐户不再存在。

          来自here

          "方法也可以具有以下属性 “幂等性”在那个(除了 错误或过期问题) N > 0 的副作用相同 请求与单个请求相同 要求。方法 GET、HEAD、PUT 和 DELETE 共享此属性。还, 方法 OPTIONS 和 TRACE 应该 没有副作用,所以是 本质上是幂等的。 "


          N > 0 个相同请求的副作用与单个请求相同。

          您认为状态代码会有所不同是正确的,但这不会影响 幂等性的核心概念 - 您可以多次发送请求而无需对服务器状态进行额外更改。

          【讨论】:

          • 副作用 !== 服务器状态
          • @wprl 关于这种“副作用”到底是什么存在争议。它可能是“服务器状态”,也可能是发送给客户端的响应。leedavis81.github.io/is-a-http-delete-requests-idempotent
          • 这里有一个论点,即第二次 DELETE 上的 404 实际上可能会改变服务器的状态:stackoverflow.com/a/45194747/317522
          • @PauloMerson 谢谢,我个人认为第二次返回是 404 还是 200 并不重要,服务器的状态没有改变,所以我很满意。
          【解决方案6】:

          来自HTTP RFC

          方法还可以具有“幂等性”,因为(除了错误或过期问题)N > 0 个相同请求的副作用与单个请求相同。

          请注意,这是“副作用”,而不是“反应”。

          【讨论】:

            【解决方案7】:

            幂等是关于请求的效果,而不是关于你得到的响应代码。

            http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.2 说:

            方法也可以具有以下属性 其中的“幂等性”(除了 错误或过期问题) N > 0 的副作用相同 请求与单个请求相同 请求。

            虽然您可能会得到不同的响应码,但向同一资源发送 N+1 个 DELETE 请求的效果可以认为是相同的。

            【讨论】:

              【解决方案8】:

              我认为同样的事情,404 - 帐户不存在。

              您可以争论 400 - 错误请求。但在 REST 的意义上,您请求对其执行操作的对象不存在。这转化为 404。

              【讨论】:

              • 要生成 400 你必须知道该对象曾经存在过,这是非常不安的。
              • @annakata,400 甚至不适用于曾经存在的资源(也许你有 410/Gone 的想法),它用于错误的请求 "The request could not be understood by the server due to malformed syntax."
              • @Bruno - 我知道这意味着什么,OP 引用了它。
              • 我认为 200 就可以了。您希望服务器的状态是该帐户已消失。哪个请求实际上使它消失了有关系吗?第二次请求仍然没有,服务器状态没有改变。
              猜你喜欢
              • 2011-10-24
              • 1970-01-01
              • 2019-06-30
              • 1970-01-01
              • 2015-09-25
              • 1970-01-01
              • 2012-10-18
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多