如果 GET 请求的响应发生变化,是否遵守幂等性?

If a GET request's response changes, is idempotency respected?

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

http://www.restapitutorial.com/lessons/idempotency.html上的这个说法让我怀疑自己对幂等性的理解。

From a RESTful service standpoint, for an operation (or service call) to be idempotent, clients can make that same call repeatedly while producing the same result. In other words, making multiple identical requests has the same effect as making a single request. Note that while idempotent operations produce the same result on the server (no side effects), the response itself may not be the same (e.g. a resource's state may change between 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,那会破坏幂等性吗?

最后,幂等性是相同的服务器一遍又一遍地工作,还是一遍又一遍地为 same/single 请求提供相同的结果?

为了理解 REST 中的幂等性,最好的起点可能是 RFC 7231

中包含的定义

A request method is considered "idempotent" if the intended effect on the server of multiple identical requests with that method is the same as the effect for a single such request.

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

// 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(GE​​T)

So does idempotency actually has something to do with server-work or a response?

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

Roy Fielding 分享了这个 observation in 2002:

HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).

如果您用 PUT/DELETE 代替 GET,用幂等代替安全,我想您会得到一个很好的画面——如果 属性 丢失是因为服务器收到了一个幂等请求的两个副本,故障是服务端处理请求不当,而不是客户端多次广播请求。

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

Idempotent methods are distinguished because the request can be repeated automatically if a communication failure occurs before the client is able to read the server's response.

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

过去,这样的对话很常见

正是因为这个原因

And finally, is idempotency same server-work over and over again, or same results over and over again for the same/single request?

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

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

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

I noticed you mentioned may produce in "Contrast this with POST; which does not promise idempotent handling. Submitting a web form twice may produce two side effects on the server....." basically rest standards declare POST as non-idempotent, but one could actually make POST an idempotent, but it would be opposite to rest standards...

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

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

So does idempotency actually has something to do with server-work or a response?

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

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

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

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

GET /users/5 How is this idempotent?

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

Furthermore if response contains some kind of UUID which is unique for each response, would that break idempotency?

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

幂等方法的另一个例子是DELETE。例如,如果您删除一个用户,则它是 gone/deleted。因为 DELETE 是幂等的,在 atempt/request 秒后删除同一个用户,用户将保持删除状态,因此状态不会改变。当然,第二个响应可能有点不同,类似于 "warning, user already deleted" 但这与幂等性无关。