2010-02-24 5 views
7

이 코드 스 니펫이 작동하지 않아 "인증 실패"가 표시됩니다. 서버로부터의 응답. 어떤 아이디어?코코아에서 Tumblr으로 POST 요청 보내기

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

당신이 나에게 텀블러의 API에 사용할 수있는 작업 코드 참조를 말할 수 :

이 코드는 유효한 멀티 파트 MIME 문자열을 만들 특히 NSString 범주, 메모를하고 싶은 것을 할 것인가? – AppAspect

답변

22

적절한 HTTP POST 요청을 작성하지 않는 것이 문제입니다. POST 요청에는 서버로 보내려는 모든 매개 변수를 포함하는 올바르게 형식이 지정된 다중 부분 MIME 인코딩 본문이 필요합니다. 매개 변수를 전혀 작동하지 않는 HTTP 헤더로 설정하려고합니다.

@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

+0

요청 본문이 UTF8 ('NSString'의'-dataUsingEncoding :'메소드를 사용하고'NSUTF8StringEncoding'을 전달)을 사용하여 인코딩 된 데이터 블로 브이기 때문에 8 비트 인코딩을 설정해야합니다. UTF8은 8 비트 인코딩으로, 7 비트 인코딩 (ASCII)으로 데이터가 손상되면 해석됩니다. Multipart MIME 인코딩을 사용하면 별도의 섹션이 포함 된 문자열을 만들 수 있습니다. 각 섹션은 경계 마커로 사용되는 상수 문자열로 구분됩니다. 경계 문자열은 완전히 임의적이지만 문자열의 경계가 아닌 내용에는 포함되어서는 안됩니다. –

+0

MIME에 대한 Wikipedia 기사는 아마도 유용 할 것입니다 : http://en.wikipedia.org/wiki/MIME#Multipart_messages –

0

this question에 대한 답변에 따라 stringByAddingPercentEscapesUsingEncoding:은 전체 이스케이프 인코딩을 수행하지 않습니다. 또한 수동으로 교체 할 인 NSMutableString의 replaceOccurencesOfString:withString:options: 방법을 사용할 수 있습니다

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

하지만, 그 방법은 더 반복하고 장황 : 어떤 이유로,이 방법의 CoreFoundation에서 버전은 그러나 않습니다. (See here)

+0

감사합니다. 나는 당신의 제안에 따라 CFURLCreate를 사용했으나 여전히 작동하지 않습니다. – kubi