乐趣区

关于前端:你惨了你的-Http-Status-0-了

前言

欢送关注同名公众号《熊的猫》,文章会同步更新,也可疾速退出前端交换群!

周一一大早就接到了测试的 Bug 反馈,其实也是用户的反馈:

【测试】挪动端偶然会呈现 操作异样,请刷新重试! 的提醒,然而从新刷新又好了,用户说好不容易填了数据一刷新就徒劳功夫了,而且在测试环境也能复现,不过目前不是那么好复现了,这是之前复现时的截图,你先看看

【低微前端】毕竟没得选)好,我看看!

这是之前(被迫 )接手的一个 React 老我的项目,其中的 申请 是通过自定义封装 XMLHttpRequest 的形式来实现的,没有应用 React CLI 的形式,而是本人基于 webpack 构建工具搭建的一个我的项目。

忠告 】看待老我的项目外围就是要足够尊重,千万不要吐槽它( 老我的项目很小气的 ),
一不小心就能给你 惊喜 ,还可能是 有限的惊喜!!!

大抵的复现步骤,如下

就是在 A 页面 B 页面 间来回进行 上一步 下一步 操作,而后再就会呈现申请异样的状况。

有了以上信息,咱们就能够开始 BUG 的摸索之路 ,上面就逐渐进行剖析, 欢送一起探讨!

无需入侵代码的调试形式

为了更好的复现问题和调试 H5 挪动端 ,咱们通常会应用一些 挪动网页前端开发工具 ,例如 vconsole,然而这意味着咱们还得去批改 代码内容 我的项目依赖 ,而且 vconsole 的交互也不太敌对( 懂的都懂 ),那么除此之外还有没有什么其余方法能够实现 无入侵的便捷调试 呢?

那天然是有的了,最罕用的就是 抓包(如 whistle,具体用法可见 Whistle 帮忙文档)、Chrome DevTools 近程调试 两种形式,这里也简略介绍一下它们的应用形式。

Chrome DevTools 近程调试手机端

这里的近程调试手机端用 Android 零碎来演示,IOS 零碎步骤是统一的,只是会有些细节差别,自行查找一下即可。

连贯 手机 和 电脑

只须要应用 数据线 手机端 电脑端 连接起来,同时将手机中的 开发人员选项 中的 USB 调试 选项开启,通常插入 USB 数据线后都会自动弹出选项框来让你进行抉择 USB 调试 模式,但局部手机的弹窗中可能没有和 USB 调试 相干的内容,如下:

此时你能够点击手机 设置,而后应用其搜寻性能疾速搜寻定位,如下:

拜访 Chrome DevTools 近程调试界面

通过 chrome://inspect/#devices 拜访调试界面,而后你就能够应用 微信拜访指标页面 或者 手机浏览器拜访指标页面,接着期待调试界面加载到对应的信息后,就能够点击对应的 inspect 进行调试了,具体如下:

whistle 抓包

这里的抓包用 Android 零碎来演示,IOS 零碎步骤是统一的,只是会有些细节差别,自行查找一下即可。

一键装置 Whistle(Mac 和 Windows)

npm i -g whistle && w2 start --init 一行命令实现如下操作:

  • 装置 Whistle
  • 启动 Whistle

    • 设置零碎代理,或不代理的白名单域名
    • 装置根证书

拜访 Whistle 界面

启动胜利后,会在终端输入可拜访的地址,默认为如下三个:

挪动端装置 CA 证书

whistle 界面点击 HTTPS 选项,在手机端扫码并下载对应的 CA 证书,目标是在代理时可能失常拜访 https 协定头 的站点,而且当初的站点大多都是应用 https 协定,因而最好操作这一步。

手机端下载 CA 证书 结束后,就须要 受权装置 手动装置 ,能够在手机 设置 中疾速搜寻查找,而后按批示装置最近下载文件即可:

保障手机端和电脑端处于同一网段

也就是保障 手机端 连贯的 WIFI 要和 电脑端 正在应用的网络是统一的即可。

设置手机端网络代理

保障是同一网段后,就须要设置代理了:

  • 找到以后连贯的 WIFI,长按而后批改网络

  • 配置代理信息

    • 服务器主机名 就是填写你的电脑的 IP,当胜利启动 Whistle 后输入的信息中会蕴含该内容,也可本人通过 ipconfig 命令查看
    • 服务器端口 就是 Whistle 代理设置的端口,默认为 8899,如果你自定义端口保持一致即可

电脑端敞开防火墙

通过上述操作后,针对大部分人来讲可能还是无奈实现代理,因为 手机端的代理申请 电脑端的防火墙 拦挡了,此时就须要将防火墙临时敞开即可。

防火墙不容许敞开怎么办?

有些小伙伴的办公电脑可能为了平安不容许你 间接敞开防火墙 ,因而你要查看防火墙对应的 白名单端口 有哪些,接着将 本来的 Whistle 代理端口 切换到 合乎的端口 即可,没有的话能够本人增加 白名单端口

值得注意的是,你切换了新的 Whistle 代理端口 后,你的 CA 证书 须要重新安装,最好是电脑端和手机端都重新安装,因为咱们要保障手机端在通过代理申请拜访代理服务时是可信赖的。

Http Status = 0

定位提醒起因

确定提醒起源

首先会提醒这个信息,那么得先确定这个提醒的起源,到底是后端返回的,还是前端自定义的,于是把 提醒文本 在我的项目中一搜寻就匹配到了,这显然是前端自定义的提醒:

剖析提醒起因

从代码逻辑上看很显著,就是当申请遇到谬误时,就会触发 error 事件,于是就会向外返回提醒文本并进行提醒,并且还会输入相应的相干信息。

配合日志定位

但值得注意的是:提醒内容蕴含了 xhr.status,再看看理论提醒内容:

再看看 监控日志,如下:

哦豁!哦豁!哦豁!

xhr.status = 0!!!

说实话我还是 第一次 遇到这种 状态码,这未免引起我的趣味,这不得持续理解理解!

Whistle 抓包 + Chrome DevTools 近程调试信息汇总

Whistle 抓包异样信息

Chrome DevTools 近程调试信息

联合以上抓取到的信息,咱们大抵失去相干的信息就是:

  • ERR\_CONTENT\_FAILED

    • 这个谬误兴许你没有见过,但它在这可 不是一个无关联的谬误 ,因为响应头的中 content-type 值为 application/json; charset=utf-8,而异样接口显然返回了 不合乎编码格局的内容 ,因而产生了 ERR_CONTENT_FAILED 谬误,即 属于同一个问题的不同体现 罢了
  • XMLHttpRequest 申请异样触发 xhr.onerror,但具体是什么异样未知,导致 xhr.status = 0

什么场景下 Http Status = 0?

XMLHttpRequest.status

XMLHttpRequest.status 是 XMLHttpRequest 响应 中的一个 无符号短整型 的数字状态码,即其值就是对应的是规范的 HTTP status codes,而 HTTP 响应状态码 又被归为以下五大类:

  • 信息响应 (100199)
  • 胜利响应 (200299)
  • 重定向音讯 (300399)
  • 客户端谬误响应 (400499)
  • 服务端谬误响应 (500599)

看着没有问题啊,然而你有没有发现 状态码 0 不在这常见的五大类中!!!

XMLHttpRequest.status 为啥是 0?

实际上在两种状况下 XMLHttpRequest.status = 0

  • 申请实现前status 的值为 0
  • 如果 XMLHttpRequest 出错,浏览器返回的 status 也为 0

申请未实现

申请未实现时 XMLHttpRequest.status = 0 的状况间接看代码示例就晓得了,如下:

var xhr = new XMLHttpRequest();
console.log('UNSENT', xhr.status); // UNSENT(未发送)0

xhr.open('GET', '/server', true);
console.log('OPENED', xhr.status); // OPENED(已关上)0

xhr.onprogress = function () {console.log('LOADING', xhr.status); // LOADING(载入中)200
};

xhr.onload = function () {console.log('DONE', xhr.status); // DONE(实现)200
};

xhr.send(null);

但这显然不合乎当初的场景,因为它是在 xhr.onerror 曾经被触发。

XMLHttpRequest 出错

这里又会分为几种状况,其实在,具体如下:

  • 申请停止,例如基于 xhrInstance.abort() 将申请停止

  • 产生跨域

  • 谬误的 URL 或 协定头

  • 服务端提前结束响应,即未失常进行响应
  • 网络断开,网络异样导致操作过程申请无奈失常发送等

前端问题?后端问题?

置信不少前端同学看到诸如下图所示的 AJAX\_ERROR 时,就间接撒手不管了,交给对应的后端去看,失常来说的确没问题,然而总归要排查起因(不然凭啥说不是你的问题),例如这里存留的疑难点是:

  • PCMobile 应用的同一个接口,PC 端各个 申请失常 ,只有 Mobile 端有 异样申请
  • Mobile 端我的项目在 本地启动 (即开发环境和已部署的测试服务),而后以浏览器的形式拜访我的项目,并按 复现步骤 进行操作时是 失常申请 ,并不会有 异样申请 的状况呈现

排除前端嫌疑

为了证实不是前端的问题,咱们就须要 列举出可能由前端引发问题的状况,而归纳起来就是一种状况,那就是 ” 申请被终止发送 “

  • 手机端的 webview 存在 缓存 Ajax 申请 的机制,当 webview 检测到某个 Ajax 申请缓存可用时,会将新的申请 勾销 掉,此时 xhr.status = 0

    • 这个是在查问材料过程中看到的一种可能,也好验证,那就是 革除缓存即可,但理论尝试后发现有效,证实不是此状况
  • 手机端 网络异样,申请未能正确发送

    • 这种状况也是不对的,因为除了用户在生产上出现异常申请外,咱们在 测试环境 也可能 复现

除此之外,认真看 Whistle 抓包 后果,异样申请的 result = 200,证实前端申请曾经失常收回,只是 后续响应过程呈现问题

排除后端嫌疑

后端可能引发问题的状况,总结起来也是一种状况,那就是 ” 提前结束响应 “

  • 对接口申请频率有限度,例如频繁申请同一个接口时,多余申请可能就会被疏忽

    • 而后端基本没有对申请做任何限度,并且再进行响应时,都会有 输入日志记录 ,在查找对应的日志后发现,对应的 异样申请并不在日志记录中,因而不是这种状况
  • 响应过程呈现编码谬误,因为在抓包过程中咱们看到了,响应体 body 中是乱码的,不合乎响应头中 content-type: application/json; charset=utf-8 的编码格局

    • 基于测试环境的后端日志输入,发现不存在异样申请的状况,因为即使是编码谬误,也会有日志记录,因而也不是这种状况

以上状况阐明,当产生异样申请时,基本没有进入到后端的 Control 层,因而后端嫌疑也排除了。

交由两头链路进行排查

既然排除了 前端 / 后端 的嫌疑,那么剩下的可能就是 两头链路 的问题了,用户在手机端拜访指标站点时的 链路,如下:

  • 手机 -> 网关 -> Nginx -> 应用服务 -> Nginx -> 网关 -> 手机

而目前看 应用服务 返回的是没有问题的,因而剩下的就交由 网关 运维 去进行排查了, 跨部门合作 会有一些工夫上不对等的问题( 懂的都懂),后续具体起因会同步到此处。

后续】排除运维嫌疑

上面是一段对话,这里只表白大抵的意思:

  • 前端 A@ 运维 C,下面的问题起初服务端加过日志看过,前端收到乱码,服务端返回的是失常的,还有服务本地部署,通过 whistle 将测试环境的接口转发到本地服务,也不会呈现乱码的状况
  • 运维 C@ 前端 B,一起帮忙看一看
  • 前端 B】上次和 前端 A 一起看过了, 查到乱码的数据是服务端返回的, 其余的就没法查上来了,看样子挪动端的接口, 应该通过了 好几层的代理,所以当初想看下响应从服务端进去后,通过 ngnix 的时候是否失常
  • 前端 A】是的,当初的想法就是追随 响应门路 的返回一层一层去排查
  • 运维 C】挪动端测试环境是 iis,不是 ng 代理

总结一下,意思就是只有 生产环境 ng 代理 测试环境 是没有 ng 代理 的,那当初的状况是: 生产环境可复现,测试环境可复现 ,因而不应该是 ng 代理 的问题, 那么只有一种可能:网关

静等 网关 排查中 ……

最初

欢送关注同名公众号《熊的猫》,文章会同步更新,也可疾速退出前端交换群!

以上就是本文的内容了,大抵通过:呈现问题 —> 复现问题 —> 排查 / 定位问题 —> 验证、排除嫌疑 —> 跨部门合作 等过程。

兴许你感觉一开始就间接交给 后端、网关、运维 去排查就好了,毕竟一通操作下来发现不是本人的问题,还节约了工夫等等。

然而要明确的是当咱们须要把某个问题交给 其余部门 进行排查 / 定位时,并不是咱们轻易说一句就能够了,因为大家都有很多事件要做,对你紧急的事件在其余部门中的优先级并不一定是最高的,此时还须要 部门和部门的负责人沟通协调,而在这之前最有必要的是先确保咱们这一方是真的不存在问题的,而后还得把你的信息同步给其余部门共事,不便他们更疾速的理解状况,更好、更快的实现相互合作和解决问题。

退出移动版