ApiCatcher 支援抓包 HTTP 傳輸大檔案的實作原理
我試用過很多 iOS 端的 HTTPS 抓包工具,都不支援擷取靜態資源檔案——或者說,請求或回應的 Body 超過某個閾值時就會被直接丟棄。有時候想排查一個檔案上傳權限問題,想抓包查看請求的完整 URL,看看用的是哪個域名、找出對應的專案,但這都做不到。
我們在開發 ApiCatcher 的過程中才了解到,原來 iOS 作業系統會限制網路擴展(Network Extension)行程的記憶體使用量。從一些資料來看,系統限制網路擴展行程最大只能使用約 50MB 的記憶體,超過的話行程就會被系統強制終止。不過這個閾值可能跟作業系統版本有關,實際測試發現在用到約 80MB 時,行程仍能正常工作。
因為存在記憶體限制,所以很多抓包工具都做了各自的限制,實現了各自的丟包策略——當請求 Body 或回應 Body 超過一定大小時就把請求丟掉。
那麼 ApiCatcher 是如何解決這個問題的呢?
考慮到一般靜態資源檔案都不會有重寫請求/回應 Body,以及透過腳本修改請求/回應 Body 的需求,所以對於靜態資源檔案,根本沒必要將請求/回應 Body 快取到記憶體中。我們改用檔案來儲存——只要是靜態資源的請求或回應,都把 Body 存到檔案裡。從接收緩衝區讀取到的位元組資料,直接寫入檔案並轉發出去,不做記憶體暫存。
一個關鍵細節:大型 HTTP 封包在 TCP 層會被拆包。假設一個 HTTP 請求傳輸的檔案是 1MB,但一個 TCP 封包可能只有 64KB。所以透過邊讀邊寫檔案的方式,一個請求只會佔用 64KB 的記憶體,而不是 1MB。當請求發送完畢或回應接收完畢後,往資料庫存入請求記錄時,將這個檔案的路徑作為 Body 欄位儲存即可。
使用這個方案需要確保使用者在刪除請求記錄時,能找到請求/回應 Body 對應的檔案並一併刪除,需要自行處理資料一致性問題。這也是為什麼 ApiCatcher 刪除資料會稍微慢一些——因為是一條條記錄走訪刪除的。但我們認為這種取捨是值得的,因為刪除功能並不經常使用,一次刪除的資料也不會很多,一萬條資料大約 5 秒就能完成。
在支援擷取圖片、影片、音訊等檔案之後,為了快速識別請求傳輸的內容,ApiCatcher 支援圖片、影片、音訊的渲染,可以直接點擊播放。我們也專門為預覽圖片、影片、音訊設計了預覽和批次匯出頁面,方便提取和匯出測試素材檔案。
我們在 iOS、Windows 與 macOS 三端都應用了相同的實現原理,即使桌面端沒有記憶體限制,這樣也能獲得更好的效能。
ApiCatcher for iOS 執行截圖:

ApiCatcher for macOS 執行截圖:
