天天看點

研究筆記:iOS中使用WebViewProxy攔截URL請求

先說明下ios中加載url的正常流程:

1.用戶端發送nsurlrequest給server

2.server傳回對應的nsurlresponse

如果被webviewproxy攔截,則流程變為:

2.這個request被webviewproxy攔截

3.proxy将修改後的新request發送給server

4.server傳回response給proxy

5.proxy将傳回的資料以url response或者回調的形式傳回給用戶端。

那麼webviewproxy的攔截原理是怎樣的呢?

首先,webviewproxy定義一個自定義的protocol(nsurlprotocol的子類)

題外話,子類必須實作nsurlprotocol的以下幾個方法才能正常工作,當然這部分工作webviewproxy已經都幫我們搞定了:

然後把urlprotocol的子類注冊到url loading system中

這樣,以後app每次發送url request時都檢查此request是否适用于webviewproxyurlprotocol(過濾條件也是使用者定義的),如果符合篩選條件,則使用webviewproxyurlprotocol來加載該url。

這裡需要注意下,原始的request和修改後的新request,可能都符合攔截條件,是以為了不使其無限制的攔截并循環處理下去,需要設定一個檢測條件,保證每個request至多被處理一次。流程見下圖。

研究筆記:iOS中使用WebViewProxy攔截URL請求

攔截的原理依據如下(nsurlprotocol的registerclass方法):

when the url loading system begins to load a request, each registered protocol class is consulted in turn to see if it can be initialized with the specified request. the first nsurlprotocol subclass to return yes when sent a caninitwithrequest: message is used to perform the url load. there is no guarantee that all registered protocol classes will be consulted. classes are consulted in the reverse order of their registration.

簡單的攔截例子:

簡單的轉發例子:

更多詳見https://github.com/marcuswestin/webviewproxy。

值得注意的是處理server傳回的response時,有三套api可供選擇:

high level api傳回image, text, html or json low level api傳回http頭和nsdata piping api:從nsurlconnection傳回data/error

注冊自定義protocol可能和其他子產品或sdk的攔截功能沖突,導緻攔截無效,依據是上文中的:the first nsurlprotocol subclass to return yes when sent a caninitwithrequest: message is used to perform the url load.

webviewproxy每次攔截成功後,都會在請求的url尾部加上一個fragment字尾(#__webviewproxyreq__)用來标記該url已攔截,防止下次再次攔截進而造成死循環。這樣有個隐患,就是url會被污染,可能影響某些正常功能。

一個解決方案是在http頭中增加一個标記字段來表示該url已經被攔截過,進而跳出循環。

繼續閱讀