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,且不說語義不對,代碼不優雅,後期也有可能帶來其餘問題。仍是要找問題的根源從而解決問題。
相關文章
相關標籤/搜索