Enviar una solicitud POST de Cocoa a Tumblr

Este fragmento de código no funciona, recibo una “Error de autenticación”. respuesta del servidor. ¿Algunas ideas?

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString:@"http://www.tumblr.com/api/write"]]; [request setHTTPMethod:@"POST"]; [request addValue:_tumblrLogin forHTTPHeaderField:@"email"]; [request addValue:_tumblrPassword forHTTPHeaderField:@"password"]; [request addValue:@"regular" forHTTPHeaderField:@"type"]; [request addValue:@"theTitle" forHTTPHeaderField:@"title"]; [request addValue:@"theBody" forHTTPHeaderField:@"body"]; NSLog(@"Tumblr Login:%@\nTumblr Password:%@", _tumblrLogin, _tumblrPassword); [NSURLConnection connectionWithRequest:request delegate:self]; [request release]; 

Tanto _tumblrLogin como _tumblrPassword se ejecutan a través de stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding en otro lugar de mi código. Mi correo electrónico de inicio de sesión es del tipo “address+test@test.com”. Funciona muy bien para iniciar sesión directamente en tumblr, pero me pregunto si el carácter “+” está causando problemas con la encoding. No se está escapando. ¿Deberia ser?


Gracias a la sugerencia de Martin, ahora estoy usando CFURLCreateStringByAddingPercentEscapes para escapar de mi nombre de usuario y contraseña. Todavía tengo el mismo problema, sin embargo, mi Autenticación está fallando.

El problema es que no está creando una solicitud HTTP POST adecuada. Una solicitud POST requiere un cuerpo con encoding MIME multiparte con formato adecuado que contenga todos los parámetros que desea enviar al servidor. Está intentando establecer los parámetros como encabezados HTTP que no funcionarán en absoluto.

Este código hará lo que usted desee, tenga en cuenta especialmente las categorías NSString que crean una cadena MIME multiparte válida:

 @interface NSString (MIMEAdditions) + (NSString*)MIMEBoundary; + (NSString*)multipartMIMEStringWithDictionary:(NSDictionary*)dict; @end @implementation NSString (MIMEAdditions) //this returns a unique boundary which is used in constructing the multipart MIME body of the POST request + (NSString*)MIMEBoundary { static NSString* MIMEBoundary = nil; if(!MIMEBoundary) MIMEBoundary = [[NSString alloc] initWithFormat:@"----_=_YourAppNameNoSpaces_%@_=_----",[[NSProcessInfo processInfo] globallyUniqueString]]; return MIMEBoundary; } //this create a correctly structured multipart MIME body for the POST request from a dictionary + (NSString*)multipartMIMEStringWithDictionary:(NSDictionary*)dict { NSMutableString* result = [NSMutableString string]; for (NSString* key in dict) { [result appendFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n",[NSString MIMEBoundary],key,[dict objectForKey:key]]; } [result appendFormat:@"\r\n--%@--\r\n",[NSString MIMEBoundary]]; return result; } @end @implementation YourObject - (void)postToTumblr { NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString:@"http://www.tumblr.com/api/write"]]; [request setHTTPMethod:@"POST"]; //tell the server to expect 8-bit encoded content as we're sending UTF-8 data, //and UTF-8 is an 8-bit encoding [request addValue:@"8bit" forHTTPHeaderField:@"Content-Transfer-Encoding"]; //set the content-type header to multipart MIME [request addValue: [NSString stringWithFormat:@"multipart/form-data; boundary=%@",[NSString MIMEBoundary]] forHTTPHeaderField: @"Content-Type"]; //create a dictionary for all the fields you want to send in the POST request NSDictionary* postData = [NSDictionary dictionaryWithObjectsAndKeys: _tumblrLogin, @"email", _tumblrPassword, @"password", @"regular", @"type", @"theTitle", @"title", @"theBody", @"body", nil]; //set the body of the POST request to the multipart MIME encoded dictionary [request setHTTPBody: [[NSString multipartMIMEStringWithDictionary: postData] dataUsingEncoding: NSUTF8StringEncoding]]; NSLog(@"Tumblr Login:%@\nTumblr Password:%@", _tumblrLogin, _tumblrPassword); [NSURLConnection connectionWithRequest:request delegate:self]; [request release]; } @end 

Según las respuestas a esta pregunta , stringByAddingPercentEscapesUsingEncoding: no realiza una encoding de escape completo. Por alguna razón, la versión de CoreFoundation de este método sí lo hace:

 [(NSString *) CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)[[self mutableCopy] autorelease], NULL, CFSTR("=,!$&'()*+;@?\n\"<>#\t :/"), kCFStringEncodingUTF8) autorelease]; 

También puede usar el método replaceOccurencesOfString:withString:options: para hacer el reemplazo de forma manual, pero ese método es más repetitivo y detallado. ( Ver aquí )