2010-02-24 14 views
7

Questo snippet di codice non funziona, ricevo "l'autenticazione non riuscita". risposta dal server. Qualche idea?Invio di una richiesta POST da Cocoa a Tumblr

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

Sia _tumblrLogin e _tumblrPassword è gestita attraverso stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding altrove nel mio codice. La mia e-mail di accesso è del tipo "[email protected]". Funziona bene per accedere direttamente a tumblr, ma mi chiedo se il carattere "+" sta causando problemi con la codifica? Non è scappato. Dovrebbe essere?


Grazie al suggerimento di Martin, Ora sto utilizzando CFURLCreateStringByAddingPercentEscapes per sfuggire il mio login e la password. Sto ancora avendo lo stesso problema, però, la mia autenticazione sta fallendo.

+0

Potete dirmi il riferimento codice di lavoro disponibili per Tumblr API? – AppAspect

risposta

22

Il problema è che non si sta creando una richiesta HTTP POST corretta. Una richiesta POST richiede un corpo con codifica MIME multiparente correttamente formattata contenente tutti i parametri che si desidera inviare al server. Stai cercando di impostare i parametri come intestazioni HTTP che non funzioneranno affatto.

Questo codice farà ciò che si vuole, nota soprattutto le NSString categorie che creano una stringa valida Multipart MIME:

@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 
+1

Santo schifo. Sarei protagonista di 10000x se potessi. Grazie per l'aiuto. Mentre ti sto prendendo in giro, ti capita di avere un link che spiega i campi intestazione (perché hai bisogno di impostare la codifica a 8 bit) e il MIMEBoundary? – kubi

+0

È necessario impostare la codifica a 8 bit perché il corpo della richiesta è un blob di dati codificati utilizzando UTF8 (utilizzando il metodo '-dataUsingEncoding:' di 'NSString' e passando in' NSUTF8StringEncoding'). UTF8 è una codifica a 8 bit, se fosse interpretata come una codifica di dati a 7 bit (ASCII) si verificherebbe corruzione. La codifica MIME multipart consente di creare una stringa che contiene sezioni separate. Ogni sezione è delineata da una stringa costante utilizzata come marker di confine. La stringa di confine è completamente arbitraria ma non deve essere contenuta nel contenuto senza limiti della stringa. –

+0

L'articolo di Wikipedia su MIME è probabilmente utile: http://en.wikipedia.org/wiki/MIME#Multipart_messages –

0

Come da risposte a this question, stringByAddingPercentEscapesUsingEncoding: non esegue una codifica di escape completa. Per qualsiasi motivo, la versione CoreFoundation di questo metodo fa, però:

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

È inoltre possibile utilizzare il metodo di NSMutableString replaceOccurencesOfString:withString:options: a fare la sostituzione manualmente, ma questo metodo è più ripetitivo e prolisso. (See here.)

+0

Grazie per questo. Ho usato il CFURLCreare ... secondo il tuo suggerimento, ma non funziona ancora. – kubi