这是「进击的Coder」的第 744 篇技术分享
作者:崔庆才
最近在做项目的过程中,有一个需求是在客户端 HTTP 请求失败后,增加一个重试机制,然后我就翻了一些有关“重试”的库,找到一个 axios-retry,在了解的过程中,我就发现了里面有一个默认的配置选项:
“By default, it retries if it is a network error or a 5xx error on an idempotent request (GET, HEAD, OPTIONS, PUT or DELETE). ”
什么意思呢?默认情况下,只有当出现网络问题,是“幂等请求”的 5xx 状态码的情况下,才会发起重试,而这里面并不包含 POST 请求。
我就好奇了,这里面的这个 idempotent request,也就是“幂等请求”究竟是什么意思呢?
带着好奇我就搜索了下,学到了新的知识,这里就跟大家分享下。
幂等请求,英文叫做 Idempotent Request,官方的文档是这个:https://developer.mozilla.org/en-US/docs/Glossary/Idempotent
官方定义如下:
“An HTTP method is idempotent if the intended effect on the server of making a single request is the same as the effect of making several identical requests. ”
意思就是,如果发出单个请求对服务器的预期效果与发出多个相同请求的效果相同,则HTTP 方法是幂等的。
其实说白了意思就是这个请求发起一次和发起多次,都对服务器结果没什么区别,一次请求后,服务器结果由 A 变成了 B,后面再发多次这样的请求,结果还是 B 不变,那这个请求就是幂等的。
我们知道,HTTP 请求一共有 GET、POST、PATCH、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT这些,那哪些是幂等,哪些是不幂等的呢。
这里面我们先分析下,其中有的请求就是一些压根不会对服务器产生任何影响的请求,比如说 GET 就是从服务器上读取信息并返回,服务器的数据根本不会被修改,这种请求就是“安全”的请求。
安全请求有哪些呢?GET、HEAD、OPTIONS、TRACE。
具体对如上三种请求的解释见官方文档:
所以,GET、HEAD、OPTIONS、TRACE 这些请求都是幂等请求。
接下来我们来分析下 POST 请求,这个是幂等的吗?
不是。
因为 POST 请求一般会用作创建一个字段,比如:
POST /add_row HTTP/1.1
POST /add_row HTTP/1.1 -> Adds a 2nd row
POST /add_row HTTP/1.1 -> Adds a 3rd row
每 POST 一次,一个字段就会被创建,所以请求一次的结果和请求多次的结果是不一样的。
所以,POST 不是幂等请求。
那 PUT 是不是呢?
是。
因为 PUT 请求一般会用作修改一个资源,而且是全部覆盖修改。
所以,发起一次 PUT 请求,服务器资源就被修改为 PUT 请求的内容了,如果再继续发起多次,那最终结果还是不变。
所以 PUT 请求是幂等请求。
同理,DELETE 是不是呢?
是。
因为 DELETE 请求是用作删除服务器资源的,发起一次 DELETE 请求,资源就被删除了,在发起多次,结果也是一样的,因为资源已经被删除了。
所以 DELETE 请求是幂等请求。
既然 PUT 是幂等请求,那么 PATCH 是不是呢?
不是。
PATCH 这个请求可能大家见的不多啊,这个请求其实和 PUT 类似,也是用来修改资源的,但 PUT 偏向于把整个资源进行修改,而 PATCH 是修改资源的某一部分。
具体 PATCH 的介绍大家可以见:https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH
原文有一个对 PATCH 是是否幂等的解释:
“A PATCH is not necessarily idempotent, although it can be. Contrast this with PUT; which is always idempotent. The word "idempotent" means that any number of repeated, identical requests will leave the resource in the same state. For example if an auto-incrementing counter field is an integral part of the resource, then a PUT will naturally overwrite it (since it overwrites everything), but not necessarily so for PATCH. ”
所以,在某些情况下,PATCH 不一定是幂等的,比如服务器的某些资源的某个字段是一个自增技术,那么每 PATCH 一次,这个就会改变一次,而 PUT 往往都是全部覆盖。
所以,在这里,PATCH 不被认为是幂等请求。
这个 CONNECT 大家可能也用的不多啊,CONNECT 请求会被用作启动与所请求资源的双向通信,它可以用来打开隧道。
具体大家可以参见:https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/CONNECT
所以,这个本身就是一种用来启动双向通信的请求,是一种逐跳请求,请求一次和多次所建立的一些连接次数也是不一样的,所以不是幂等请求。
好了,这里就总结了幂等和非幂等请求的一些定义和分析。
幂等请求有:GET, HEAD, PUT, DELETE, OPTIONS, TRACE
非幂等请求有:POST, PATCH, CONNECT
看完这篇文章,以后大家再问起幂等请求相关的问题,肯定就不会懵了吧!