iOS webview 网络请求代理调研

背景

在iOS中,除了普通请求(NSURLSession、NSURLConnection)以外,还有一种webview的请求,这是iOS的一种UI组件,可直接调用其loadRequest方法,发起请求,webview会把response以html的形式加载到其界面上。

我们主要对于常用的UIWebview、WKWebview的网络请求尝试使用Cronet进行代理进行了调研分析。

问题及解决方案

UIWebview
发现问题:
Response无法手动获取,这个应该是webview的一个通病,即没发通过回调等方式获取到字符串形式的response header 及 response。

解决办法:
这里有个帖子使用UIWebview的回调方式拿到response,
stackoverflow-uiwebview

但我测试无效,通过NSCachedURLResponse *resp = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request];获取的总是null。

因此目前这个问题处于无解状态中。

WKWebview
问题1:
使用post的方法时,无法将body post成功
详见帖子:
WKWebview-postBody
帖子里提到iOS8 和 9有这个问题,但我实测,iOS10也有这个问题(真机和模拟器都试了)

解决方案涉及一些前端JS处理,感觉不是很靠谱而且把事情变得更复杂了,详情可见帖子。

问题2:
无法被NSURLProtocol拦截,这意味着无法代理它的请求。
使用WKWebview,期待命中CroNet时,却发现它仅仅命中了CanInitRequest函数,然后就出来了,继续走的系统网络库

详见帖子:
WKWebview-NSURLProtocol
自测确实是这样。

解决方法:
需要拿到WKBrowsingContextController,通过register方法,让http/https的请求进入NSURLProtocol。
wkwebview-codes
自测这样的话,可以命中CroNet
如图为让WKWebview命中CroNet后加载出来的页面
wkwebview-demo

风险:这个好像使用了苹果未公开的API

wkwebview-danger