一般,咱們只會用 img 標籤或 Image 對象來加載圖片資源,但實際上 Image 也常被用來發請求做數據的上報,一方面緣由就是不須要考慮跨域,並且一般數據上報也不須要處理響應。可是,若是在代碼中使用 Image 來發送一些業務請求等,則要考慮其必要性了,若是沒有必要,還應該使用 ajax 來發送請求,不然可能埋下一個隱蔽的坑。ajax
最近接手了一個用戶反饋的餘額沒有顯示的 bug,因爲自身無法在現有信息的條件下復現 bug,又難以從代碼中找到邏輯問題(仍是缺乏經驗),只能經過打日誌的方式找用戶配合聯調,通過幾天的折騰才最終定位到是使用 image 來發請求引發的 bug。那麼使用 image 來發請求是如何引發這個 bug 的?存在什麼隱患?跨域
首先,來看下用戶反饋的截圖:(其中暗含了一個關鍵信息)瀏覽器
登陸態問題bash
經過查看該用戶的後臺日誌信息,發現用戶的帳戶信息請求的 Cookie 中缺乏了一個關鍵的票據信息,致使獲取不到餘額,因而發現獲取該票據的請求在日誌中並無找到。所以,能夠首先判斷,是登陸態問題致使用戶取不到餘額信息,可是,爲什麼關鍵的獲取票據請求後臺沒有收到呢?服務器
請求發出了沒有?cookie
遇到請求後臺沒有收到,首先懷疑的是邏輯的問題:應該是存在邏輯漏洞致使在某條件下沒有發送該請求。而後經過本地調試以及對該段邏輯的梳理,實際上並沒能發現存在請求不被髮送的可能。到這一步,就很難走下去了,沒有更多的信息,且業務邏輯幾乎肯定沒有問題。不過,我多少也開始以爲奇怪,爲啥這裏是用 Image 來發送請求:url
var imgReq = document.createElement('img');
imgReq.onload = imgReq.onerror = function () {
...
}
imgReq.src = url;
複製代碼
打更多日誌spa
只經過代碼,即使能從理論上判斷邏輯沒有問題,可是沒有辦法保證運行起來就的確如此。無奈之下,只能在代碼中打上更多日誌,而後聯繫用戶操做,並將手機上 vconsole 打印的日誌發給我(這是十分須要用戶配合的 OTZ)。很幸運,用戶很配合地按個人指示操做了,我才能拿到用戶手機客戶端的日誌來進行分析。調試
根據日誌,我能確定請求必定是發出去了,可是服務器也的確沒有收到請求。這讓我以爲詭異,我開始懷疑是 img.src 這種請求方式的問題了,這才驚悚地發現,**用戶的頭像沒有顯示!**這就是那個暗含的關鍵信息!一開始我覺得用戶的頭像就是灰色的,因而沒有注意,可是在與用戶溝通的 QQ 羣裏,用戶是有頭像的。不難想到,這極有可能和瀏覽器無圖模式有關。然而,在個人手機上依舊不能復現,因而我只剩這樣的假設了:日誌
帶着這樣的假設,我增長了 ajax 的請求方式,不得不讓用戶再試一次,很快就在日誌中證明了這個假設:
...
cookie: ... // 無票據(img 請求以後)
...
cookie: ... // 有票據(ajax 請求以後)
複製代碼
因而我在用戶同機型的手機上也復現了這個問題。。。(爲何不早點找同機型的手機復現😭 OTZ)
在瀏覽器無圖模式下(這裏具體場景爲 QQ 瀏覽器),且在某些機型的手機上,經過 Image 動態發起請求是有可能被攔截的! 上報請求被攔截其實也還能接受(畢竟如今還有多少人在意流量呢),可是業務請求被攔截就可能直接影響功能了。爲避免這樣的隱患,仍是應該儘可能避免用 Image 來發業務請求。