Fly攔截全域性Ajax請求
大多數情況下,我們的 Ajax 請求都是通過前端的開發庫、框架發出的,如 jQuery、axios 或者 Fly。這些庫自身都會有一些請求/響應鉤子,用於預處理 Ajax請求和響應。但是,如果你沒有使用這些網路庫,又或是你並不是網頁的開發者,而你需要分析某個網頁的所有Ajax請求,又或是你是一個應用開發者,你的webview中需要攔截所有網頁的網路請求(網頁並不是你開發的)…… 這種時候,你就需要攔截全域性的 Ajax 請求.
原理
無論你的應用是通過那個框架或庫發起的 Ajax 請求,最終都會迴歸到 XMLHttpRequest
。 所以,攔截的本質就是替換瀏覽器原生的 XMLHttpRequest
XMLHttpRequest
,然後在請求過程中根據具體業務邏輯決定是否需要發起網路請求,如果需要,再建立真正的 XMLHttpRequest
例項。
Fly 攔截全域性ajax
我們知道,在 Fly 中,XMLHttpRequest
就是一個 http engine。所以我們要攔截,只需要自定義一個engine替換掉全域性的XMLHttpRequest
就行,而 Fly 提供了快速生成 engine 的工具,所以我們可以很方便實現攔截。
我們先看一個簡單的例子,功能是輸出每次網路請求 url 和 method。
實現
var log = console.log;
//切換fly engine為真正的XMLHttpRequest
fly.engine = XMLHttpRequest;
var engine = EngineWrapper(function (request, responseCallback) {
console.log(request.url, request.method)
//發起真正的ajax請求
fly.request(request.url, request.data, request)
.then(function (d) {
responseCallback({
statusCode: d.engine.status,
responseText: d.engine.responseText,
statusMessage: d.engine.statusText
})
})
.catch(function (err) {
responseCallback({
statusCode:err.status,
statusMessage:err.message
})
})
})
//覆蓋預設
XMLHttpRequest = engine;
axios.post("../package.json").then(log)
我們用 axios 發起一個請求測試一下:
axios.post("../package.json").then(log)
//控制檯輸出
> http://localhost:63341/Fly/package.json POST
> {data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
可以看到控制檯中輸出了請求的 url 和 method,我們的攔截成功了。而 第二行的結果物件是axios then
打印出的。
因為 Fly支援切換engine, 我們可以直接先將 fly engine 切換為真正的 XMLHttpRequest
,然後再覆蓋,這樣fly中的網路請求都是通過真正的 XMLHttpRequest
發起的 (事實上, 瀏覽器環境下 fly 預設的 engine本就是 XMLHttpRequest
,無需手動切換,此處為了清晰,故手動切換了一下)。fly 會根據request物件自動同步請求頭。如果想阻止請求,直接在 adapter 中 return 即可。
其它攔截方法
Github上的開源庫 Ajax-hook 也可以攔截全域性的的ajax請求,不同的是,它可以攔截ajax請求的每一步,每一個回撥,不僅強大,而且也很輕量(1KB)。和上面通過 fly engine 攔截的方式相比 ,Ajax-hook的攔截粒度更細,但Ajax-hook由於使用了ES5的 getter
、setter
,所以不支援IE9以下的瀏覽器。