iOS NSURLProtocol的具体使用方法详解

2020-01-21 02:35:14于丽

2.拦截整个App中所有的网络请求


//直接在AppDelegate中的didFinishLaunchingWithOptions注册网络拦截代码
//注册Protocol
[NSURLProtocol registerClass:[CustomURLProtocol class]];
NSURLProtocol使用实例

#define URLProtocolHandledKey @"URLProtocolHandledKey"
 
+ (BOOL)canInitWithRequest:(NSURLRequest *)request{
 //只处理http和https请求
  NSString *scheme = [[request URL] scheme];
  if ( ([scheme caseInsensitiveCompare:@"http"] == NSOrderedSame ||
   [scheme caseInsensitiveCompare:@"https"] == NSOrderedSame)){
    //看看是否已经处理过了,防止无限循环
    if ([NSURLProtocol propertyForKey:URLProtocolHandledKey inRequest:request]) {
      return NO;
    }
    return YES;
  }
  return NO;
}
 
+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
   /** 可以在此处添加头等信息 */
  NSMutableURLRequest *mutableReqeust = [request mutableCopy];
  mutableReqeust = [self redirectHostInRequset:mutableReqeust];
  return mutableReqeust;
}
 
+(NSMutableURLRequest*)redirectHostInRequset:(NSMutableURLRequest*)request{
  if ([request.URL host].length == 0) {
    return request;
  }
 
  NSString *originUrlString = [request.URL absoluteString];
  NSString *originHostString = [request.URL host];
  NSRange hostRange = [originUrlString rangeOfString:originHostString];
  if (hostRange.location == NSNotFound) {
    return request;
  }
  //定向薄荷喵到主页
  NSString *ip = @"bohemiao.com";
 
  // 替换域名
  NSString *urlString = [originUrlString stringByReplacingCharactersInRange:hostRange withString:ip];
  NSURL *url = [NSURL URLWithString:urlString];
  request.URL = url;
 
  return request;
}
 
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b{
  return [super requestIsCacheEquivalent:a toRequest:b];
}
 
- (void)startLoading{
  NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
  //标示该request已经处理过了,防止无限循环
  [NSURLProtocol setProperty:@YES forKey:URLProtocolHandledKey inRequest:mutableReqeust];
  self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
  //使用NSURLSession也是一样的
}
 
- (void)stopLoading{
  [self.connection cancel];
}
 
- (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
  [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
 
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
  [self.client URLProtocol:self didLoadData:data];
}
 
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
  [self.client URLProtocolDidFinishLoading:self];
}
 
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
  [self.client URLProtocol:self didFailWithError:error];
}

上面用到的一些NSURLProtocolClient方法


@protocol NSURLProtocolClient <NSObject>
 
//请求重定向
- (void)URLProtocol:(NSURLProtocol *)protocol wasRedirectedToRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
 
// 响应缓存是否合法
- (void)URLProtocol:(NSURLProtocol *)protocol cachedResponseIsValid:(NSCachedURLResponse *)cachedResponse;
 
//刚接收到Response信息
- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy;
 
//数据加载成功
- (void)URLProtocol:(NSURLProtocol *)protocol didLoadData:(NSData *)data;
 
//数据完成加载
- (void)URLProtocolDidFinishLoading:(NSURLProtocol *)protocol;
 
//数据加载失败
- (void)URLProtocol:(NSURLProtocol *)protocol didFailWithError:(NSError *)error;
 
//为指定的请求启动验证
- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
 
//为指定的请求取消验证
- (void)URLProtocol:(NSURLProtocol *)protocol didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
 
@end