Utilizando NSURLProtocol con NSURLSession

Mi aplicación utiliza NSURLConnection para comunicarse con el server. Usamos https para la comunicación. Para manejar la authentication de todas las requestes en un solo lugar, utilicé NSURLProtocol y NSURLProtocol authentication en delegates de esa class. Ahora he decidido usar NSURLSession lugar de NSURLConnection . Estoy intentando hacer que NSURLProtocol funcione con NSURLSession . NSURLSession una tarea y utilicé NSURLProtocol por

 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]; 

CustomHTTPSProtocol que es mi class NSURLProtocol , se parece a esto

 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, NSURLCnetworkingential *cnetworkingential))completionHandler { NSLog(@"challenge..%@",challenge.protectionSpace.authenticationMethod); if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) { [challenge.sender useCnetworkingential:[NSURLCnetworkingential cnetworkingentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; } else { [challenge.sender continueWithoutCnetworkingentialForAuthenticationChallenge: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 

Se llama al inicio de carga y también se hace un desafío de authentication, pero se detiene la carga inmediatamente después de eso.

Código de error -999 "Cancelado" se devuelve después de algún time. didReceiveData no se llama.

Note:NSURLProtocol and the Authentication Process worked fine with NSURLConnection.

Qué me estoy perdiendo ?? Mis preguntas son

  1. Registro [NSURLProtocol registerClass: [CustomHTTPSProtocol class]]; funcionó bien con NSURLConnection, pero ¿cómo hacer una Resistencia para NSURLProtocol a nivel mundial con NSURLSession?

  2. ¿Por qué se rechazan las requestes en NSURLProtocol (misma URL y lógica trabajadas con la connection de LAN) con URLSession y cómo hacer que NSURLProtocol funcione con URLSession?

Por favor, ayúdame y avísame si quieres más detalles.

Sé que esto es antiguo, pero el problema que tienes está en tu método didReceiveChallenge. Está terminando el método llamando al

 [challenge.sender continueWithoutCnetworkingentialForAuthenticationChallenge:challenge]; 

o

 [challenge.sender useCnetworkingential:[NSURLCnetworkingential cnetworkingentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge]; 

Lo que debe hacer es utilizar el manejador de finalización para enviar los resultados. Se vería así:

 completionHandler(.UseCnetworkingential, NSURLCnetworkingential(forTrust: challenge.protectionSpace.serverTrust) 

o

 completionHandler(.PerformDefaultHandling, nil) 

Estos están en Swift 2.0, pero deberían traducirse muy bien a Obj-C.

El logging de un NSURLProtocol personalizado con NSUrlsession es el mismo que en NSURLConnection.

NSURLSession Api (NSURLSessionDataTask y otras classs de tareas) cuando se usa con NSUrlProtocol personalizado no puede gestionar correctamente los desafíos de authentication HTTP. Esto funcionaba como se esperaba en iOS 7.x y se rompió en iOS 8.x.Raised un radar de Apple y mi radar se cerró diciendo que era un duplicado de otro radar y todavía veo que el radar original todavía está abierto. Por lo tanto, creo que este problema todavía no está arreglado por Apple a partir de hoy.

Espero no haber llegado tarde con la respuesta 🙂

Mi vago recuerdo es que NSURLSession utiliza automáticamente todos los protocolos registrados a nivel mundial. Por lo tanto, no debería volver a registrarlo, pero tampoco debería ser perjudicial hacerlo.

Me pregunto si la request de URL se está copyndo, en cuyo caso su labeldo personalizado podría no funcionar, y es posible que vea una recursión infinita hasta que scope un límite interno. ¿Ha intentado configurar un encabezado de request en su lugar?