如果GET请求的响应发生变化,是否会尊重幂等性?

时间:2017-07-04 12:31:42

标签: rest api api-design idempotent

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

关于http://www.restapitutorial.com/lessons/idempotency.html的这一陈述让我怀疑我对幂等性的理解。

  

从RESTful服务的角度来看,对于操作(或服务调用)   要是幂等的,客户可以反复进行同样的呼叫   产生相同的结果。换句话说,使多个相同   请求与发出单个请求具有相同的效果。注意   而幂等操作在服务器上产生相同的结果(没有   副作用),反应本身可能不一样(例如a   资源的状态可能会在请求之间发生变化)。

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

如果我有

,会让我感到困惑
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,这种UUID对于每个响应都是唯一的,那会破坏幂等性吗?

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

2 个答案:

答案 0 :(得分:3)

  

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

它指的是后续相同类型请求之后的服务器状态。

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

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

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

  

GET / users / 5   这是幂等的?

您可以根据需要使用GET方法调用此网址,服务器不会更改其内部状态,即用户的last_name;如果它没有改变它,那么它保持不变,所以GET是幂等的。

  

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

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

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

答案 1 :(得分:2)

为了理解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(GET)== oldState.andThen(GET).andThen(GET)

  

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

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

Roy Fielding分享了此observation in 2002

  

HTTP不会尝试要求GET的结果是安全的。它的作用是要求操作的语义是安全的,因此它是实现的错误,而不是接口或接口的用户,如果发生任何导致财产损失的结果(金钱,BTW,为了这个定义,它被认为是财产。)

如果你用PUT / DELETE代替GET,并且幂等于安全,我认为你得到了一个很好的图片 - 如果由于服务器收到两个幂等请求的副本而发生属性丢失,则错误是服务器处理请求不正确,而不是客户端多次广播请求。

这很重要,因为它允许在不可靠的网络上进行至少一次传送。来自RFC 7231

  

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

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

在这一天,像这样的对话很常见

Internet explorer warning about retrying a form submission

正是出于这个原因

  

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

在服务器上工作。幂等变化类似于SET或REPLACE(又名,比较和交换)。

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

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

  

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

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

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