【问题标题】:If a GET request's response changes, is idempotency respected?如果 GET 请求的响应发生变化,是否尊重幂等性?
【发布时间】:2017-12-07 22:23:15
【问题描述】:

我阅读了很多关于 REST API 的内容,但我总是偶然发现术语幂等性。基本上 GET、HEAD、PUT、DELETE 和 OPTIONS 都是幂等的,而 POST 不是。

http://www.restapitutorial.com/lessons/idempotency.html 上的这句话让我怀疑我对幂等性的理解。

从 RESTful 服务的角度来看,对于操作(或服务调用) 为了幂等,客户端可以重复调用相同的调用,同时 产生相同的结果。换句话说,使多个相同的 requests 与发出单个请求具有相同的效果。注意 而幂等操作在服务器上产生相同的结果(没有 副作用),响应本身可能不同(例如 资源的状态可能会在请求之间改变)。

那么幂等性实际上与服务器工作或响应有关吗?

如果我有什么让我感到困惑

GET /users/5

返回

{
"first_name" : "John",
"last_name" : "Doe",
"minutes_active": 10
}

然后在一分钟后做同样的请求,我会得到

GET /users/5
{
"first_name" : "John",
"last_name" : "Doe",
"minutes_active": 11
}

这个幂等性如何?

此外,如果响应包含某种对每个响应都是唯一的 UUID,那会破坏幂等性吗?

最后,幂等性是一遍又一遍的相同服务器工作,还是对于同一个/单个请求一遍又一遍的相同结果?

【问题讨论】:

  • 我建议修改标题中的问题。

标签: rest api api-design idempotent


【解决方案1】:

要了解 REST 中的幂等性,最好的起点可能是 RFC 7231 中包含的定义

如果使用该方法的多个相同请求对服务器的预期效果与单个此类请求的效果相同,则该请求方法被认为是“幂等的”。

对于“效果”,想想副作用。当服务器宣传特定操作是幂等的时,它告诉您(语义上重要的)副作用最多会发生一次。

// the guarantee of an idempotent operation
oldState.andThen(PUT(newState)) === oldState.andThen(PUT(newState)).andThen(PUT(newState))

Safe 方法本质上是幂等的,因为它们对服务器没有影响。

// the guarantee of a safe operation
oldState === oldState.andThen(GET)

// 因此,幂等操作的保证很简单 oldState.andThen(GE​​T) == oldState.andThen(GE​​T).andThen(GE​​T)

那么幂等性实际上与服务器工作或响应有关吗?

服务器工作。更一般地说,它是对更改状态命令的接收者的约束。

Roy Fielding 分享了这个observation in 2002

HTTP 并不试图要求 GET 的结果是安全的。它所做的是要求操作的语义是安全的,因此如果发生任何导致财产损失的事情(金钱,顺便说一句,为了这个定义,被认为是财产)。

如果你用 PUT/DELETE 代替 GET,用幂等代替安全,我认为你得到了一个很好的图景——如果由于服务器收到了一个幂等请求的两个副本而发生财产损失,那么错误是服务器处理了请求不正确,而不是客户端多次广播请求。

这很重要,因为它允许通过不可靠的网络至少交付一次。来自 RFC 7231

幂等方法的区别在于,如果在客户端能够读取服务器的响应之前发生通信故障,请求可以自动重复。

将此与 POST 进行对比;它不承诺幂等处理。提交网络表单两次可能在服务器上产生两个副作用,因此客户端实现(和中间组件,如代理)不能假设重复丢失的请求是安全的。

在过去,这样的对话很常见

正是因为这个原因

最后,幂等性是一遍又一遍的相同服务器工作,还是对于同一个/单个请求一遍又一遍的相同结果?

在服务器上工作。幂等更改类似于 SET 或 REPLACE(也称为比较和交换)。

当然,响应可能会有所不同。例如,conditional PUT 将包含元数据“指示在将方法语义应用于目标资源之前要测试的前提条件。”

因此,服务器可能会更改状态以响应接收到 put 的第一个副本,发回200 OK 以向客户端指示请求成功;但是在接收到第二个请求时,服务器会发现资源现在更改的状态不再与提供的元数据匹配,并会回复412 Precondition Failed

我注意到您在“将其与 POST 进行对比;它不承诺幂等处理。提交 Web 表单两次可能会对服务器产生两个副作用.....”中提到的可能会产生,基本上其余标准将 POST 声明为非幂等的,但实际上可以使 POST 成为幂等的,但这与其他标准相反...

不,这不太对。 HTTP 规范不要求 POST 支持幂等语义——这意味着不允许客户端和中介假定它支持。服务器控制自己的实现;它可能提供对 POST 请求的幂等处理。

但服务器无法向客户端(或中介)宣传此功能,以便他们可以利用它。

【讨论】:

    【解决方案2】:

    那么幂等性实际上与服务器工作或响应有关吗?

    指后续同类型请求后的服务器状态。

    因此,假设客户端发出一个请求,将服务器的旧状态(例如 S1)更改为新状态 S2,然后再次发出相同的请求。

    如果方法是幂等的,那么保证第二个请求不会再次改变服务器的状态,它将保持S2。

    但是如果方法不是幂等的,就不能保证状态会保持不变,S2;它可能会更改为服务器想要的任何状态,例如 S3 或 S1。因此,在这种情况下,如果发生通信错误,客户端不应再次发送命令,因为结果与第一次发送命令时不同。

    获取 /users/5 这怎么算幂等的?

    您可以使用GET 方法多次调用此url,并且服务器不会更改其内部状态,即用户的last_name;如果它不改变它,那么它保持不变,所以 GET 是幂等的。

    此外,如果响应包含某种对每个响应都是唯一的 UUID,那会破坏幂等性吗?

    响应与后续相同类型请求后的服务器状态无关,因此每次请求后响应可能是唯一的,并且请求仍然是幂等的。例如,在您问题的 GET 请求中,minutes_active 每分钟都会更大,这不会使 GET 不是幂等的。

    幂等方法的其他示例是 DELETE。例如,如果您删除一个用户,那么它就会消失/删除。因为 DELETE 是幂等的,在第二次尝试/请求删除同一用户后,该用户将保持已删除状态,因此状态不会改变。当然,第二个响应可能有点不同,例如“警告,用户已删除”,但这与幂等性无关。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      • 2018-08-03
      • 1970-01-01
      相关资源
      最近更新 更多