servicio consumir iphone http ios nsurlconnection

iphone - consumir - swift http request



iOS: ¿Cómo puedo recibir HTTP 401 en lugar de-1012 NSURLErrorUserCancelledAuthentication (5)

Es realmente simple. Ahora bien, es cierto que la solicitud asincrónica es realmente una buena ayuda. Pero debes tener en cuenta que es solo una ayuda. Http es solo un protocolo para la creación de redes y, por lo tanto, NO DEBE interactuar con el usuario. En otras palabras, ambos casos son uno y el mismo.

Si no desea utilizar el asistente de sincronización, le sugiero que muestre al usuario un cuadro de diálogo de inicio de sesión y repita su solicitud hasta que el usuario presione cancelar.

[editar]

solo por información, personalmente prefiero curl. Funciona como un encanto en casi todas partes;)

Tengo un problema similar al descrito en el siguiente enlace.

NSHTTPURLResponse statusCode regresa a cero cuando debería ser 401

Yo uso [NSURLConnection sendSynchronousRequest:returningResponse:error:] para obtener datos de un servidor.

Cuando NSURLConnection recibe el código HTTP 401, no devuelve nada más que un objeto de error con el código -1012 del NSURLErrorDomain. -1012 corresponde a NSURLErrorUserCancelledAuthentication . Como tengo que analizar el encabezado HTTP, necesito obtener el error original y no lo que NSURLConnection hizo de él.

¿Hay alguna manera de recibir el paquete original 401 http?


Estaba enfrentando el problema de no recibir el código de error 401 No autorizado (recibía una respuesta nula y el método didReceiveResponse no se llamaba) en vez de recibir el error cancelado -999. El error que estaba cometiendo en mi código es: En didReceiveChallenge: delegar método,

if (challenge.previousFailureCount == 0) { //handle certificate trust completionHandler (NSURLSessionAuthChallengeUseCredential, newCredential); } else { completionHandler (NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil); }

El NSURLSessionAuthChallengeCancelAuthenticationChallenge daba como resultado el error -999 y no se obtuvo ninguna respuesta 401. En cambio, cuando utilicé completionHandler (NSURLSessionAuthChallengePerformDefaultHandling, nil); Recibí 401 respuestas en didReceiveResponse: delegar método como se esperaba.

Nota de la documentación de iOS https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html , Si cancelamos la sesión de URL, se informará como cancelada, pero no como un error 401 en respuesta.

Note: NSURLSession does not report server errors through the error parameter. The only errors your delegate receives through the error parameter are client-side errors, such as being unable to resolve the hostname or connect to the host. The error codes are described in URL Loading System Error Codes. Server-side errors are reported through the HTTP status code in the NSHTTPURLResponse object. For more information, read the documentation for the NSHTTPURLResponse and NSURLResponse classes.


Me sorprende la respuesta "recomendada" a este hilo.

Bien, estoy seguro de que usar los métodos de versión asíncrona es mejor, pero aún no explica por qué la función sendSynchronousRequest te permite pasar una variable para devolver el código de respuesta, pero en algunas circunstancias, simplemente devuelve nada.

Son 4 años desde que se informó este problema, estoy usando XCode 6.2 con iOS 8.2, y este antiguo error todavía está presente.

Mis servicios web devuelven deliberadamente un error 401 cuando el nombre de usuario y la contraseña de un usuario no son correctos.

Cuando mi aplicación de iPhone llama a este servicio (con las credenciales incorrectas) ...

NSHTTPURLResponse *response = nil; NSData *data = [ NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error ];

.. la response se devuelve como nula (por lo que no puedo probar la respuesta HTTP 401), el error recibe un mensaje -1012 envuelto así:

Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x174869940 {NSErrorFailingURLStringKey=https://mywebservice.com/Service1.svc/getGroupInfo/6079, NSUnderlyingError=0x174e46030 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)", NSErrorFailingURLKey=https://mywebservice.com/Service1.svc/getGroupInfo/6079}

y la función sendSynchronousRequest devuelve una larga cadena XML que contiene ... bueno ... esto ...

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Request Error</title> <style>BODY { color: #000000; background-color: white; font-family: Verdana; margin-left: 0px; margin-top: 0px; } #content { margin-left: 30px; font-size: .70em; padding-bottom: 2em; } A:link { color: #336699; font-weight: bold; text-decoration: underline; } A:visited { color: #6699cc; font-weight: bold; text-decoration: underline; } A:active { color: #336699; font-weight: bold; text-decoration: underline; } .heading1 { background-color: #003366; border-bottom: #336699 6px solid; color: #ffffff; font-family: Tahoma; font-size: 26px; font-weight: normal;margin: 0em 0em 10px -20px; padding-bottom: 8px; padding-left: 30px;padding-top: 16px;} pre { font-size:small; background-color: #e5e5cc; padding: 5px; font-family: Courier New; margin-top: 0px; border: 1px #f0f0e0 solid; white-space: pre-wrap; white-space: -pre-wrap; word-wrap: break-word; } table { border-collapse: collapse; border-spacing: 0px; font-family: Verdana;} table th { border-right: 2px white solid; border-bottom: 2px white solid; font-weight: bold; background-color: #cecf9c;} table td { border-right: 2px white solid; border-bottom: 2px white solid; background-color: #e5e5cc;}</style> </head> <body> <div id="content"> <p class="heading1">Request Error</p> <p>The server encountered an error processing the request. The exception message is ''Access is denied.''. See server logs for more details. The exception stack trace is: </p> <p> at System.ServiceModel.Dispatcher.AuthorizationBehavior.Authorize(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</p> </div> </body> </html>

Vamos, Apple, arregla tus errores ...


Sí. Deja de usar la API síncrona. Si usa la API asíncrona basada en delegados, tendrá mucho más control sobre la conexión. Con esta API, excepto en los casos en que se encuentra un error antes de que se reciba el encabezado HTTP, siempre recibirá -connection:didReceiveResponse: que le da acceso a los campos de encabezado HTTP (encapsulados en un objeto NSURLResponse ). También puede implementar autenticación utilizando los métodos delegados relevantes si así lo desea.


Solución:

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue new] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSHTTPURLResponse *aResponse = (NSHTTPURLResponse *)response; int statusCodeResponse = aResponse.statusCode; NSString *strError = [NSString stringWithFormat:@"%@", [connectionError description]]; if ([strError rangeOfString:@"Code=-1012"].location != NSNotFound) { statusCodeResponse = 401; }

No es la mejor solución, pero funciona!