网络请求

IOS 网络请求url拦截

2017-02-27  本文已影响353人  某个胖子

研究笔记:iOS中使用WebViewProxy拦截URL请求

概述
先说明下iOS中加载url的正常流程:
1.客户端发送NSURLRequest给server
2.server返回对应的NSURLResponse

如果被WebViewProxy拦截,则流程变为:
1.客户端发送NSURLRequest给server
2.这个request被WebViewProxy拦截
3.proxy将修改后的新request发送给server
4.server返回response给proxy
5.proxy将返回的数据以url response或者回调的形式返回给客户端。

那么WebViewProxy的拦截原理是怎样的呢?

拦截原理
首先,WebViewProxy定义一个自定义的protocol(NSURLProtocol的子类)

@interface WebViewProxyURLProtocol : NSURLProtocol
题外话,子类必须实现NSURLProtocol的以下几个方法才能正常工作,当然这部分工作WebViewProxy已经都帮我们搞定了:

这里需要注意下,原始的request和修改后的新request,可能都符合拦截条件,所以为了不使其无限制的拦截并循环处理下去,需要设置一个检测条件,保证每个request至多被处理一次。流程见下图。
Copy_of_Copy_of_CLTV_DOL_Flowchart

拦截的原理依据如下(NSURLProtocol的registerClass方法):

[WebViewProxy handleRequestsMatching:[NSPredicate predicateWithFormat:@"host MATCHES[cd] '[foo|bar]'"] handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
简单的转发例子:

[WebViewProxy handleRequestsWithHost:@"example.proxy" handler:^(NSURLRequest req, WVPResponse res) {
NSString
proxyUrl = [req.URL.absoluteString stringByReplacingOccurrencesOfString:@"example.proxy" withString:@"example.com"];
NSURLRequest
proxyReq = [NSURLRequest requestWithURL:[NSURL URLWithString:proxyUrl]];
[NSURLConnection connectionWithRequest:proxyReq delegate:res];
}];
更多详见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已经被拦截过,从而跳出循环。

上一篇下一篇

猜你喜欢

热点阅读