bug修復錄-qq瀏覽器中post請求時body為空

wingtao發表於2019-04-04

近期專案中遇到一個bug,其中解決過程比較有意思,特此記錄下來。有一天看到報警記錄有一個500服務端的錯誤,量很少,一週都不一定有一個,先根據伺服器裡的本地日誌拿到了當時請求的相關資訊像UA、cookie什麼的,確定了請求是來自iPhone上的qq瀏覽器,因為我們業務在手機瀏覽器裡沒有入口,所以這種情況很少。於是找來iPhone下載QQ瀏覽器嘗試復現問題。

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時用排除法,先確定問題所在

  1. 首先排查發post請求過程有沒有問題,因為有可能依賴的某個包在國產QQ瀏覽器上有相容性問題,但一路排查發起過程都沒什麼問題,最後不用依賴包,直接用XMLHttpRequest手寫了個post請求依然不好使,排除了發請求的依賴包的問題。

  2. 排查專案是否對發請求有影響,有些內部的監控上報的包可能會對XMLHttpRequest中方法做改寫,於是一路刪除懷疑的依賴包,最後單純返回了一個簡單頁面,頁面內發一個post請求,body依然為空,至此排除了所有依賴包的影響(這個過程很費時間,這個思路不是很好)。

  3. 排查到這就有點蛋疼了,Google搜了下看有沒有人和我遇到同樣的問題,發現qq瀏覽器論壇上17年就有人提出這個問題了,相似的帖子大概有七八個,但有官方迴應的也就一兩個,回覆也只是說讓升級瀏覽器。。。使用者升級瀏覽器還行,開發者得解決問題啊,排查到這已經確定了一點,就是qq瀏覽器肯定對post請求的支援是有問題的。

  4. 意識到qq瀏覽器有問題,下意識想針對qq瀏覽器做下相容處理。開始想post改成get請求,但是post中的body不是簡單地資料結構,如果是以下資料改成get還好,如:

     body
     {
     	name: 'frontend',
     	age: '8',
     }
    複製程式碼

但是遇到較為複雜的資料結構就不好使了,如:

	{
		times: [123,234,2423,12],
		favour: {
			detail: 'sdadfa',
		}
	}
複製程式碼

因為改成get後是通過query來傳遞資料的,query是隻支援字串的;另外這種方式隱隱約約感覺會坑很大,所以排除了這種方式。於是嘗試另一種方式,把body資料放到header裡面,反正HTTP協議裡對header大小是沒做限制的,所以這樣乾的

	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,且不說語義不對,程式碼不優雅,後期也有可能帶來其他問題。還是要找問題的根源從而解決問題。

相關文章