整理了下关于CustomHTTPProtocol的知识,顺带画了张流程图,方便自己梳理。
CustomHTTPProtocol.m流程 (3).png1.初始化请求canInitWithRequest
不是所有请求都要经过定制的协议来走,我们自己定制实现的Protocol可以根据不同条件筛选请求,同时对请求做更完整的包装定义。
在NSURLProtocol.h的interface定义中,以下两个方法是比较关键的:
- canInitWithRequest:
- (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;
使用canInitWithRequest:我们可以筛选出可以使用当前协议的request,其它的忽略掉,直接走其它协议或者默认实现。
2.规范化request canonicalRequestForRequest
这个方法用于过滤请求,通过shouldAccept来判断是否接受该request,例如由于只接受http和https所以不是这两者的请求则不接受,以及判断是否被标记,被标记意味着已经经过本类处理,则本类不再处理。
3.对request进行打标记flag
很多情况下,具体的通信实现最终可能还是要采用系统自身提供的默认实现,但却又需要我们做过滤包装。通常的办法是我们对request按需求场景做特定处理,最后返给系统,走默认实现。
但这样这个request很有可能会再次进入这个protocol,所以通常在对request进行完第一次处理后,打个标,下次进入canInitWithRequest时直接过滤掉。
所谓的打标就会涉及到对request的属性操作,需要如下方法:
- (id)propertyForKey:(NSString *)key inRequest:(NSURLRequest *)request;
- (void)setProperty:(id)value forKey:(NSString *)key inRequest:(NSMutableURLRequest *)request;
- (void)removePropertyForKey:(NSString *)key inRequest:(NSMutableURLRequest *)request;
大家可能会想,这样的方法不应该是NSURLRequest类的么?或者是Category?
是的,看起来是可以这样的。但大家注意到这是NSURLProtocol的类(+)方法,也就是说这里的API是以工具方法提供的。
4.协议内容实现和与client交互
下面说实现协议最重要的部分,做一个Protocol总要有实现的。重写如下两个方法,在方法内部实现定制
- (void)startLoading;
- (void)stopLoading;
在实现这两个方法时,通过URL Loading System和上层打交道是一定要有的。这就是NSURLProtocol.h中的另一部分内容——NSURLProtocolClient。NSURLProtocolClient是一个Objective-C的protocol,定义了一些方法。我们在实现startLoading/stopLoading时,我们只要在有必要和系统交互时拿到self.client对象调用就好,client会由上下文实例化好供我们使用。
- 对请求代理回调进行处理
在代理回调中处理authentication challenge,请参考文章:iOS-HTTPS
参考文献:
1.iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求
2.定制实现NSURLProtocol
3.对苹果CustomHTTPProtocol的理解
4.NSURLProtocol和NSRunLoop的那些坑
5.iOS-HTTPS
网友评论