Wysłanie zapytania o POST od Cocoa do Tumblr

Ten fragment kodu nie działa, dostaję " Authentication Failed."odpowiedź z serwera. Jakieś pomysły?

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

Zarówno _tumblrLogin jak i _tumblrPassword są uruchamiane stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding gdzie indziej w moim kodzie. Mój adres e-mail logowania ma postać "[email protected]". działa dobrze przy logowaniu się bezpośrednio do Tumblra, ale zastanawiam się, czy znak " + " powoduje problemy z kodowaniem? Nie ucieknie. A powinno być?


Dzięki sugestii Martina, używam teraz CFURLCreateStringByAddingPercentEscapes do escape mój login i hasło. Nadal mam ten sam problem, ale moje uwierzytelnianie zawodzi.

Author: kubi, 2010-02-24

2 answers

Problem polega na tym, że nie tworzysz odpowiedniego żądania HTTP POST. Żądanie POST wymaga odpowiednio sformatowanego wieloczęściowego kodu MIME zawierającego wszystkie parametry, które chcesz wysłać do serwera. Próbujesz ustawić parametry jako nagłówki HTTP, które w ogóle nie będą działać.

Ten kod zrobi to, co chcesz, zwróć uwagę zwłaszcza na kategorie NSString, które tworzą poprawny wieloczęściowy ciąg 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
 22
Author: Rob Keniger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-28 22:36:14

Zgodnie z odpowiedziami na to pytanie, stringByAddingPercentEscapesUsingEncoding: nie wykonuje pełnego kodowania escape. Z jakiegokolwiek powodu, Wersja CoreFoundation tej metody robi, jednak:

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

Możesz również użyć metody nsmutablestring replaceOccurencesOfString:withString:options: do ręcznego zastąpienia, ale ta metoda jest bardziej powtarzalna i słowna. (zobacz tutaj .)

 0
Author: Martin Gordon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:38