Using NSURLProtocol with NSURLSession
我的应用程序使用
我创建了一个任务,并由
使用了
1 2 3 4 5 6 | NSMutableURLRequest *sampleRequest = [[NSMutableURLRequest alloc]initWithURL:someURL]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; configuration.protocolClasses = @[[CustomHTTPSProtocol class]]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; NSURLSessionDataTask *task = [session dataTaskWithRequest:checkInInfoRequest]; [task resume]; |
我的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | static NSString * const CustomHTTPSProtocolHandledKey = @"CustomHTTPSProtocolHandledKey"; @interface CustomHTTPSProtocol () <NSURLSessionDataDelegate,NSURLSessionTaskDelegate,NSURLSessionDelegate> @property (nonatomic, strong) NSURLSessionDataTask *connection; @property (nonatomic, strong) NSMutableData *mutableData; @end @implementation CustomHTTPSProtocol + (BOOL)canInitWithRequest:(NSURLRequest *)request { if ([NSURLProtocol propertyForKey:CustomHTTPSProtocolHandledKey inRequest:request]) { return NO; } return [[[[request URL]scheme]lowercaseString]isEqualToString:@"https"]; } + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { return request; } - (void) startLoading { NSMutableURLRequest *newRequest = [self.request mutableCopy]; [NSURLProtocol setProperty:@YES forKey:CustomHTTPSProtocolHandledKey inRequest:newRequest]; NSURLSession*session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; self.connection = [session dataTaskWithRequest:newRequest]; [self.connection resume]; self.mutableData = [[NSMutableData alloc] init]; } - (void) stopLoading { [self.connection cancel]; self.mutableData = nil; } -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler { NSLog(@"challenge..%@",challenge.protectionSpace.authenticationMethod); if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; } } - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { [self.client URLProtocol:self didLoadData:data]; NSLog(@"data ...%@ ",data); //handle data here [self.mutableData appendData:data]; } - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (!error) { [self.client URLProtocolDidFinishLoading:self]; } else { NSLog(@"error ...%@ ",error); [self.client URLProtocol:self didFailWithError:error]; } } @end |
调用开始加载,也执行身份验证质询,但此后立即调用停止加载。
Error code -999"Cancelled" is returned after some time. didReceiveData is not called.
我想念什么?我的问题是
Registering [NSURLProtocol registerClass:[CustomHTTPSProtocol class]]; worked fine with NSURLConnection but how to Resister for NSURLProtocol Globally with NSURLSession ?.
Why are the requests getting failed in NSURLProtocol(same URL and logic worked withURLConnection) with URLSession and how to get NSURLProtocol working with URLSession ?.
请帮助我,如果您需要更多详细信息,请告诉我。
使用NSUrlsession注册自定义NSURLProtocol与使用NSURLConnection进行注册的方式相同。
NSURLSession Api(NS??URLSessionDataTask和其他任务类)与自定义NSUrlProtocol一起使用时,无法正确处理HTTP身份验证质询。
这在iOS 7.x上可以正常工作,在iOS 8.x上坏了。举起一个苹果雷达,我的雷达关闭了,说它是另一个雷达的副本,我仍然看到原来的雷达仍然打开。因此,我认为到目前为止,Apple尚未解决此问题。
希望我回答的时间还不算太晚:)
我知道这很旧,但是您遇到的问题出在didReceiveChallenge方法中。您正在通过调用
结束该方法
1 | [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge]; |
或
1 | [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; |
您需要做的是使用完成处理程序发送结果。看起来像这样:
1 | completionHandler(.UseCredential, NSURLCredential(forTrust: challenge.protectionSpace.serverTrust) |
或
1 | completionHandler(.PerformDefaultHandling, nil) |
它们在Swift 2.0中,但是应该可以很好地转换为Obj-C。
我模糊的回忆是NSURLSession自动使用任何全局注册的协议。因此,您无需再次注册,但这样做也无妨。
我想知道是否复制了URL请求,在这种情况下,您的自定义标记可能无法工作,并且您可能会看到无限递归,直到达到某个内部限制为止。您是否尝试过设置请求标头?