2014-01-15 82 views
2

我需要拦截客户端在呼叫成功完成时在应用程序中进行的网络呼叫。 我发现一个解决方案是实现NSURLProtocol抽象类并注册到应用程序。如何使用NSURLProtocol拦截iOS中的网络呼叫(REST)

这似乎解决了我的问题,但后来我碰壁了,请求超时。 我使用AFNetworking最新的1.x版本,因为我需要支持iOS 5.0。

所以,现在我需要找到如何延长初始请求的超时或其他更适合我的问题的解决方案。

这是我所做的。 的NSURLProtocol实现:

@implementation SLKURLProtocol 

+ (NSURLRequest*) canonicalRequestForRequest:(NSURLRequest *)request 
    { 
    return request; 
    } 

+ (BOOL) canInitWithRequest:(NSURLRequest *)request 
    { 
    return [[[request URL] scheme] isEqualToString:@"http"]; 
    } 

- (void) startLoading 
    { 
    dispatch_async(kBgQueue, 
     ^{ 
     NSLog(@"Intercept Request startLoading"); 
     NSURLRequest* request = self.request; 
     NSLog(@"URL: %@", request.URL); 
     NSLog(@"HTTP Method: %@", request.HTTPMethod); 
     NSLog(@"Data: %@", [NSString stringWithUTF8String:[request.HTTPBody bytes]]); 
     }); 
    } 

- (void) stopLoading 
    { 
    dispatch_async(kBgQueue, 
     ^{ 
     NSLog(@"Intercept Request stopLoading"); 
     }); 
    } 

@end 

的网络视图控制器:

@implementation SLKViewController 

- (void) viewDidLoad 
    { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
    [NSURLProtocol registerClass:[SLKURLProtocol class]]; 
    [self initRequest]; 
    } 

- (void) initRequest 
    { 
    NSMutableURLRequest* urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://requestb.in/19kcum21"] 
      cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f]; 
    [urlRequest setHTTPMethod:@"POST"]; 

    NSMutableData* postData = [NSMutableData data]; 
    [postData appendData:[@"REQUEST AFNETWORKING" dataUsingEncoding:NSUTF8StringEncoding]]; 
    [urlRequest setHTTPBody:postData]; 
    AFHTTPRequestOperation* operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest]; 

    [operation setCompletionBlockWithSuccess: 
     ^(AFHTTPRequestOperation *operation, id responseObject) 
     { 
     NSString* serverResponse = [operation responseString]; 
     NSLog(@"AFNetworking Response: %@", serverResponse); 
     } failure: 
      ^(AFHTTPRequestOperation *operation, NSError *error) 
     { 
     NSLog(@"AFNetworking Error: %@", error.description); 
     }]; 

    [operation start]; 
    } 

@end 

这里是日志输出:

2014-01-15 17:07:19.518 InterceptionHttp[510:1303] Intercept Request startLoading 2014-01-15 17:07:19.520 InterceptionHttp[510:1303] URL: http://requestb.in/19kcum21 2014-01-15 17:07:19.521 InterceptionHttp[510:1303] HTTP Method: POST 2014-01-15 17:07:19.522 InterceptionHttp[510:1303] Data: REQUEST AFNETWORKING 2014-01-15 17:07:29.522 InterceptionHttp[510:400b] Intercept Request stopLoading 2014-01-15 17:07:29.522 InterceptionHttp[510:70b] AFNetworking Error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo=0x8a5cb10 {NSErrorFailingURLStringKey= http://requestb.in/19kcum21 , NSErrorFailingURLKey= http://requestb.in/19kcum21 , NSLocalizedDescription=The request timed out., NSUnderlyingError=0x8a5c220 "The request timed out."}

编辑:

jqyao答案后和读取我学到的文章一些关于NSURLProtocol子类的主题。但不幸的是,我仍然无法拦截HTTP,这意味着我希望原始请求正常继续。

与此同时,如果我添加3行调用URLProtocol委托选择器,原始请求将继续,但有数据而不是服务器的响应。

以下是我在startLoading方法中添加的内容。

[[self client] URLProtocol:self didReceiveResponse:[[NSURLResponse alloc] init] cacheStoragePolicy:NSURLCacheStorageNotAllowed]; 
[[self client] URLProtocol:self didLoadData:data]; 
[[self client] URLProtocolDidFinishLoading:self]; 

这是我的输出日志。

2014-02-04 17:27:22.253 InterceptionHttp[419:3a03] Intercept Request startLoading 2014-02-04 17:27:22.254 InterceptionHttp[419:3a03] URL: http://requestb.in/tsvc14ts 2014-02-04 17:27:22.255 InterceptionHttp[419:3a03] HTTP Method: POST 2014-02-04 17:27:22.255 InterceptionHttp[419:3a03] Data: { 'message': 'JSON_MESSAGE' } 2014-02-04 17:27:22.258 InterceptionHttp[419:70b] AFNetworking Response: { 'message': 'JSON_MESSAGE' } 2014-02-04 17:27:22.260 InterceptionHttp[419:1303] Intercept Request stopLoading

回答

3

我建议你把这篇文章http://robnapier.net/offline-uiwebview-nsurlprotocol和实现https://github.com/rnapier/RNCachingURLProtocol上看看。你多久看一次超时问题?

+0

嗨,谢谢,很快就会进行调查,总是超时! –

+0

我已阅读文章,并遵循一些代码,最终我发现自定义协议将按照ObjC的作品以反向注册顺序执行。我尝试调用URLProtocol选择器,现在它得到AFNetworking报告请求数据的响应!检查更新的答案。 –

+0

RNCachingURLProtocol.m是拦截http的好例子。在你的情况下,你需要添加代码'NSURLConnection * connection = [NSURLConnection connectionWithRequest:connectionRequest delegate:self]; [self setConnection:connection];'将连接转发到较低级别的网络堆栈。然后在每个委托函数中,使用NSURLProtocolClient将数据传回给应用程序。 – jqyao