bug修复录-qq浏览器中post请求时body为空

近期项目中遇到一个bug,其中解决过程比较有意思,特此记录下来。有一天看到报警记录有一个500服务端的错误,量不多,一周都不必定有一个,先根据服务器里的本地日志拿到了当时请求的相关信息像UA、cookie什么的,肯定了请求是来自iPhone上的qq浏览器,由于咱们业务在手机浏览器里没有入口,因此这种状况不多。因而找来iPhone下载QQ浏览器尝试复现问题。ios

bug情景复现

描述:iPhone中某些版本的QQ浏览器中提交订单时,报错提示服务端异常,经抓包排查发现提交订单时post请求的body为空,content-length为0,因而开始了此次艰难蛋疼的bugfix过程。浏览器

其中手机是iPhone 8p,QQ浏览器版本9.1.0.4110,ios版本11.0,请求UA是Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0 MQQBrowser/9.1.0 Mobile/15B87 Safari/604.1 MttCustomUA/2 QBWebViewType/1 WKType/1。(虽然这些对此次后期排查修复都没什么蛋用,但有时仍是颇有用的)。服务器

思路

我的喜欢debug时用排除法,先肯定问题所在cookie

  1. 首先排查发post请求过程有没有问题,由于有可能依赖的某个包在国产QQ浏览器上有兼容性问题,但一路排查发起过程都没什么问题,最后不用依赖包,直接用XMLHttpRequest手写了个post请求依然很差使,排除了发请求的依赖包的问题。数据结构

  2. 排查项目是否对发请求有影响,有些内部的监控上报的包可能会对XMLHttpRequest中方法作改写,因而一路删除怀疑的依赖包,最后单纯返回了一个简单页面,页面内发一个post请求,body依然为空,至此排除了全部依赖包的影响(这个过程很费时间,这个思路不是很好)。frontend

  3. 排查到这就有点蛋疼了,Google搜了下看有没有人和我遇到一样的问题,发现qq浏览器论坛上17年就有人提出这个问题了,类似的帖子大概有七八个,但有官方回应的也就一两个,回复也只是说让升级浏览器。。。用户升级浏览器还行,开发者得解决问题啊,排查到这已经肯定了一点,就是qq浏览器确定对post请求的支持是有问题的。post

  4. 意识到qq浏览器有问题,下意识想针对qq浏览器作下兼容处理。开始想post改为get请求,可是post中的body不是简单地数据结构,若是是如下数据改为get还好,如:测试

    body
     {
     	name: 'frontend',
     	age: '8',
     }
    复制代码

可是遇到较为复杂的数据结构就很差使了,如:spa

{
		times: [123,234,2423,12],
		favour: {
			detail: 'sdadfa',
		}
	}
复制代码

由于改为get后是经过query来传递数据的,query是只支持字符串的;另外这种方式隐隐约约感受会坑很大,因此排除了这种方式。因而尝试另外一种方式,把body数据放到header里面,反正HTTP协议里对header大小是没作限制的,因此这样干的debug

const xhr = new XMLHttpRequest();
	xhr.setRequestHeader({
		x-body: JSON.stringify(body),
	})
复制代码

服务端接收时再判断header中是否有x-body,当时想的这种方式是可行的,但现实很残酷,这种方式测试时发现抓包都抓不到,说明请求都没发出来,把body数据改小点,测试是能够的,这说明qq浏览器对header里数据大小是有限制的,(这就是理论与现实的矛盾的问题,http协议其实对这些都是没有限制的,但各个浏览器会有各自不一样的限制),这种方式也宣布流产,此时已经中度蛋疼了。

  1. 后来想POST请求body为空这种问题仍是性质挺严重的,其余页面是否是有这种问题呢?在别人页面打开找post请求发现人家的请求是有body的,这就说明咱们项目中是确定有问题的,可是同时有其余人反馈有过这种问题,说明qq浏览器也是有问题的。
  2. 既然这边很差debug到具体缘由,那就向qq浏览器反馈下吧。先是向qq浏览器论坛提交了反馈,可是看以前帖子无人回应,估计此次反馈也会迟迟得不到回应;又找了QQ浏览器的反馈群,在群里反馈这个问题,这个回应仍是比较快的,一天之后就有人回应了,在提供了问题页面,复现版本后,qq浏览器那边首先回应是让升级浏览器看好很差使,我是开发者啊,保留现场还来不及呢怎么再去破坏现场,把这种敷衍怼回去后,他们认真帮复现了下,最后确认了问题是旧版本的一个bug,最新的9.1.1上已经解决了,事情到这总算有个眉目了,可是还没算解决啊,他们回应说要么提醒用户升级到最新浏览器,要么页面请求时,服务器响应一个content-type,我擦,咱们的问题终于出现了,这说明咱们页面请求时没有返回content-type啊,他们解释说页面返回时没有带content-type,致使识别有问题。我检查了下果真没有返回content-type,以前一直纠结在接口请求上了,却忽视了页面请求时的header内容。
  3. 问题找到了,也便容易解决了,在项目服务端渲染返回页面时加上了content-type,顺手向项目用的脚手架提了issue和pr。至此问题终于算是解决了

总结

问题就是qq浏览器中post请求时body为空,须要在页面返回时有content-type,不然在一些版本的qq浏览器中会识别有问题,致使body为空。

在这个过程当中,我意识到两个问题

  1. 遇到问题,特别是比较难解决的问题,必定不要轻易放弃,深挖下去总能有些意想不到的东西,这就是经验,并且解决了也会有成就感。
  2. 遇到不是颇有思路的问题,不要慌,不要轻易用打补丁作兼容的方式来解决问题,好比post改get,且不说语义不对,代码不优雅,后期也有可能带来其余问题。仍是要找问题的根源从而解决问题。
相关文章
相关标签/搜索