背景说明
之所以想hook XMLHTTPRequest是因为NSURLProtocol导流WKWebview有body丢失问题。要解决这个问题,目前一个思路,通过注入JS代码的方式来解决这个问题,在NSURLProtocol的didReceiveData函数中,我们可以第一时间接收到请求返回的HTML数据,然后我们把hook XMLHTTPRequest的send方法和open的JS函数插入到HTML之中,然后再返回给系统。
在hook代码里面要重组url和body参数并且加上标识位,然后重新发起get请求,然后这时候我们的NSURLProtocol会再次捕获这个重新发起的get请求,根据我们请求中的标记,辨别出是我们重组过的请求,将请求中的参数取出来(我们把body存放在文件里,做好标识,便于一一对应request,方便读取),再次拼接以后塞入body发起post请求。
1.Hook XMLHTTPRequest
我打算分成两步来进行,第一部分已经完成,第二部分还在进行中。
1.1 hook XMLHTTPRequest发起的请求
<script
///如下内容插入到body标签内
<script>
hookAjax(
// hook functions and callbacks of XMLHttpRequest object
{
onreadystatechange: function (xhr) {
console.log("onreadystatechange called: %O", xhr)
//return true
},
onload: function (xhr) {
console.log("onload called: %O", xhr)
xhr.responseText = "hook" + xhr.responseText;
//return true;
},
open: function (arg, xhr) {
console.log("open called: method:%s,url:%s,async:%s", arg[0], arg[1], arg[2], xhr)
arg[1] += "?hook_tag=1";
//统一添加请求头
},
send: function (arg, xhr) {
console.log("send called: %O", arg[0])
xhr.setRequestHeader("_custom_header_", "ajaxhook")
},
setRequestHeader: function (arg, xhr) {
console.log("setRequestHeader called!", arg)
},
// hook attributes of XMLHttpRequest object
timeout: {
setter: function (v, xhr) {
//timeout shouldn't exceed 10s
return Math.max(v, 1000);
}
}
}
);
$.get().done(function (d) {
console.log(d.substr(0, 30) + "...")
//use original XMLHttpRequest
console.log("unhook")
unHookAjax()
$.get().done(function (d) {
console.log(d.substr(0, 10))
})
})
</script>
通过控制台的log,验证后,可以拦截到请求。
1.2 将hook代码接入NSURLProtocol
时间关系,这部分还在验证。这是下个阶段的任务。