Cache Control参数引发的Bug

596 阅读3分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

前言

最近手头上接了一个App,主要是进行维护与修复Bug。

说实话,这种活最累,查找一个他人写的逻辑或者页面,经常半天就过去。

而且上线的时候居然有个非常严重的Bug没有修复,哎,只好硬着头皮上。

今天就说说这个Bug。

Bug复现

APP端有一个手机密码找回功能,需要调用一个接口,入参是手机号,请求后,返回一个验证码。

非常简单的一个需求。

结果,问题来了,同一个手机号码,安卓App,每次请求后,都会返回验证码。

而iOS这边,第一次请求成功后,返回了验证码,之后App中不管怎么请求,都不会返回验证码了,但是跟踪后台的响应,每次请求都到了App端的后台。

分析

我和安卓的大佬,对比iOS与Android端的请求入参,这是一个get请求,只需要将手机号拼接到api后面即可,入参一致,pass

然后,我们对了请求头,请求头中的Map的key与value拼写无误,pass

最后,我在对比每次服务器返回的响应体的时候发现了问题:每次返回的响应时间都是一样的,而且都是第一次请求成功返回了验证码的时间

注意,就是下面这段JSON中的Date,每次都是相同的。

{
    "Cache-Control" = "max-age=259200";
    Connection = "keep-alive";
    "Content-Type" = "application/json";
    Date = "Mon, 05 Aug 2021 08:19:53 GMT";
    Expires = "Thu, 08 Aug 2021 08:19:53 GMT";
    Server = "nginx/1.10.3 (Ubuntu)";
    "Transfer-Encoding" = Identity;
    "X-Application-Context" = "??APP:uat-product,swagger:9800";
}

也就是说,一旦iOS端请求成功,获取到了验证码之后,之后请求该接口后台返回的都是最近一次的成功缓存。

这是为什么呢?

跟踪并发现问题

短信接口服务,本质上是App请求App后台,App后台再去请求短信服务商:

流程图.jpg

App后台做的仅仅是将App的请求数据转发到短信服务商,一般这种请求我们叫透传。

那么为何同样的请求参数与请求头,安卓这边透传没有问题,而iOS这边透传就有问题呢?

于是我们始模拟测试接口,通过postman进行该接口的调试,发现每次都能请求成功,并且获取到验证码,而且响应体返回的响应时间Date也是实时变化的。

最后发现,postman每次请求的时候,都会在请求头中带一个iOS和Android端都没有带的参数:

{"Cache Control": "no-cache"}

于是抱着死马当活马医的想法,在iOS端的请求头中添加了该请求头参数,就好了,就好了,就好了。。。

但是为何安卓端不用带就是好的呢?后台的给的解释是安卓这边的安全级别要低一些。

我想请教各位大佬这究竟是怎么一回事呢?

参考文档

百度百科 Cache-control

总结

短信服务商对于过于频繁的请求短信接口应该是会有一个判断的,而读取成功的缓存也应该是有一个时限性。

不知道为何在iOS端的请求的时候,就变成了长期读取缓存而不进行真正的请求,而通过配置{"Cache Control": "no-cache"}可以忽略掉读取缓存进行请求。

我们下期见。