2012-02-03 38 views
5

Estoy tratando de obtener un JSON de mi dirección url de hudson y autenticar mi aplicación (Mac OS X) utilizando la Autenticación HTTP.Obtener JSON con Autenticación HTTP con AFNetworking

Siguiendo el ejemplo que estoy usando:

// AppDelegate.m 
- (void) doSomething { 
    [[CommAPIClient sharedClient] getPath:@"/computer/api/json" parameters:nil 
success:^(AFHTTPRequestOperation *operation, id responseObject) { 
     NSLog(@"Name: %@", [responseObject valueForKeyPath:@"totalExecutors"]); 

    } failure:nil]; 
} 

// CommAPIClient.m 
+ (CommAPIClient *) sharedClient { 
    static CommAPIClient *_sharedClient = nil; 
    static dispatch_once_t onceToken; 

    dispatch_once(&onceToken, ^{ 
     AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate]; 
     _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString: [appDelegate.hudsonTextField stringValue]]]; 
    }); 
    return _sharedClient; 
} 

- (id) initWithBaseURL:(NSURL *)url { 
    self = [super initWithBaseURL:url]; 
    if (self){ 
     [self registerHTTPOperationClass:[AFJSONRequestOperation class]]; 

     AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate]; 
     userName = [appDelegate.userTextField stringValue]; 
     password = [appDelegate.passwdTextField stringValue]; 

     [self setAuthorizationHeaderWithUsername:userName password:password]; 
     [self setDefaultHeader:@"Accept" value:@"application/json"]; 
    } 
    return self; 
} 

quiero obtener la lista del equipo para mostrar en mi desplegable, pero estas dos líneas no trabaja en conjunto: [auto setAuthorizationHeaderWithUsername: nombre de usuario: contraseña ]; [self setDefaultHeader: @ "Aceptar" valor: @ "application/json"];

Si sólo tiene que utilizar la primera línea, mis obras authetication, pero recibo que el error porque trato de obtener una clave:

2012-02-03 02:43:57.542 HudsonSlave[7523:707] An uncaught exception was raised 
2012-02-03 02:43:57.542 HudsonSlave[7523:707] [<NSConcreteData 0x100850000> valueForUndefinedKey:]: this class is not key value coding-compliant for the key totalExecutors. 

2012-02-03 02:43:57.623 HudsonSlave[7523:707] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSConcreteData 0x100850000> valueForUndefinedKey:]: this class is not key value coding-compliant for the key totalExecutors.' 

Si usar la segunda línea, mi autenticación devolverá un error 403.

¿Alguien podría ayudar con el problema?

Gracias y disculpas por cualquier error en inglés.

Thiago

+0

¿Qué sucede cuando usa ambas líneas, exactamente? – mattt

+0

@mattt, el error me dijo que faltaba un tipo de contenido, así que, he agregado una tercera línea: [self setDefaultHeader: @ "Content-Type" value: @ "application/json"]; y el error es: Código de error = Dominio com.alamofire.networking.error = -1,016 "Tipo de contenido esperado {( "text/javascript", "application/json", "text/json" )}, obtuvo application/javascript "UserInfo = 0x100513190 {NSLocalizedDescription = Tipo de contenido esperado {( " text/javascript ", " application/json ", " text/json " )}, obtuvo application/javascript, NSErrorFailingURLKey = http://hudson.concretecorp.com.br/computer/api/json} – unnamedd

Respuesta

7

"Tipo de contenido esperado {("text/javascript", "application/json", "text/json")}, consiguió application/javascript"

igual el error decía que la solicitud esperaba uno de text/javascript, application/json o text/json, pero el servidor envió application/javascript (que es un tipo de mime incorrecto para JSON).

O haga que su servidor responda con el tipo de mime correcto, o (quizás más fácil) cambie manualmente la línea en AFJSONRequestOperation que especifica qué tipos de mime son accesibles. Hay una alternativa menos hacky para cambiar el código de la biblioteca que implica la creación de subclases, pero eso es probablemente mucho más problema de lo que vale en tu caso.

+0

Solo una nota al margen: no es necesario configurar el encabezado 'Content-Type' en' AFHTTPCLient'. Eso se establecerá automáticamente según la forma en que se serialicen los parámetros de su solicitud. – mattt

14

Me encontré con este problema con la API de Flickr y terminé subclases AFJSONRequestOperation, que resultó ser trivial. Solo hay que reemplazar el método de clase defaultAcceptableContentTypes thusly, por ejemplo:

+ (NSSet *)defaultAcceptableContentTypes; 
{ 
    return [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain", nil]; 
} 

Luego, en mi subclase AFHTTPClient, acabo de registrar mi subclase como la clase de operación HTTP predeterminado:

[self registerHTTPOperationClass:[CCFFlickrJSONRequestOperation class]]; 

ACTUALIZACIÓN 2013-09- 09 14-52-47:

el nombre del método es ahora + (NSSet *)acceptableContentTypes

+0

Después de probar muchas soluciones, la subclasificación de AFJSONRequestOperation y la sustitución de los tipos de contenido aceptables por defecto fue la más limpia y mejor. ¡GRACIAS! – DZenBot

+5

Parece que en 'AFNetworking 1.0RC1' este método ha cambiado a' + (NSSet *) acceptableContentTypes' – bearMountain

+0

nota al margen: a veces también es necesario agregar @ "text/html" – BabyPanda

4

Si es una cosa de una sola vez en lugar de la subclasificación de todo el AFJSON RequestOperation objeto sólo puede establecer directamente los tipos de contenido aceptables para cualquier cosa que necesite:

AFJSONRequestOperation *operation = blah blah blah 

[operation setAcceptableContentTypes:[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain",@"text/html", nil]]; 

[operation start]; 
+0

setAcceptableContentTypes no parece existir en AFNetworking 1.1 –

5

En realidad ahora puede añadir más tipos de contenido fácilmente:

[AFHTTPRequestOperation addAcceptableContentTypes:[NSSet setWithObjects:@"text/html", nil]]; 
+2

¿Dónde está el lugar correcto para ponerlo? – Shmidt

+0

Buena pregunta, Shmidt. – Morkrom

2

A partir de AFNetworking 2.0, la serialización ya no forma parte de las clases RequestOperation y se delega en las clases de serialización. Si usa 2.0, desea hacer algo como esto (en general, creo que es la mejor solución para extender tipos de contenido aceptables en lugar de reemplazarlo; nunca se sabe qué valores base tendrá en futuras versiones de AFNetworking SDK):

AFHTTPRequestOperationManager *requestManager = [AFHTTPRequestOperationManager manager]; 

NSMutableSet *contentTypes = [requestManager.responseSerializer.acceptableContentTypes mutableCopy]; 
[contentTypes addObject:@"text/html"]; 
[contentTypes addObject:@"text/plain"]; 
// ... etc ... 
requestManager.responseSerializer.acceptableContentTypes = [contentTypes copy]; 

Si decide utilizar un objeto AFHTTPRequestOperation directamente, simplemente reemplace "requestManager.responseSerializer" con "myOperationObject.responseSerializer".

+0

Gracias bro.working –

Cuestiones relacionadas