2010-02-24 70 views
7

此代碼段不起作用,我得到「身份驗證失敗」。來自服務器的響應。有任何想法嗎?從Cocoa發送POST請求到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]; 

兩個_tumblrLogin_tumblrPassword通過stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding其他地方在我的代碼運行。我的登錄電子郵件格式爲「[email protected]」。它可以直接登錄到tumblr,但是我想知道「+」字符是否會導致編碼問題?它沒有被轉義。它應該是?


由於馬丁的建議,我現在使用CFURLCreateStringByAddingPercentEscapes逃脫我的登錄名和密碼。我仍然有同樣的問題,但是,我的身份驗證失敗。

+0

你能告訴我供的tumblr API的工作代碼參考? – AppAspect 2011-07-14 10:43:28

回答

22

問題是您沒有創建正確的HTTP POST請求。 POST請求需要格式正確的多部分MIME編碼主體,其中包含要發送到服務器的所有參數。您正在嘗試將參數設置爲根本不起作用的HTTP標頭。

該代碼會做你想要什麼,尤其要注意NSString類別創建一個有效的多部分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

聖潔的廢話。如果可以的話,我會將這個10000x出現。謝謝你的幫助。雖然我已經找到了你,但是你碰巧有鏈接解釋headerFields(爲什麼需要設置8位編碼)和MIMEBoundary? – kubi 2010-02-24 23:41:30

+0

您需要設置8位編碼,因爲請求的主體是使用UTF8編碼的數據(使用'NSString'的'-dataUsingEncoding:'方法並傳遞'NSUTF8StringEncoding')。 UTF8是一種8位編碼,如果它被解釋爲7位編碼(ASCII),則會發生數據損壞。多部分MIME編碼允許您創建包含單獨部分的字符串。每個部分由用作邊界標記的常量字符串劃定。邊界字符串是完全任意的,但不能包含在字符串的非邊界內容中。 – 2010-02-25 00:12:26

+0

有關MIME的維基百科文章可能很有用:http://en.wikipedia.org/wiki/MIME#Multipart_messages – 2010-02-25 00:13:29

0

根據對this question的回答,stringByAddingPercentEscapesUsingEncoding:不會執行完整的轉義編碼。無論出於何種原因,這種方法的CoreFoundation版本確實,但是:

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

您還可以使用的NSMutableString的replaceOccurencesOfString:withString:options:方法做手工更換,但該方法是多重複和繁瑣。 (See here。)

+0

謝謝你。我確實使用了CFURLCreate ...按照你的建議,但它仍然不起作用。 – kubi 2010-02-24 17:31:37