AFNetworking 3.0+ POST with headers and HTTP Body

這篇文章主要用來記錄遭遇的問題,由於花費超過一下午的工作時間,所以記錄下來希望有需要的人可以減少人生的花費在這問題上。

一般來說,透過AFNetworking連線,會長這樣:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@”text/html”, nil]; 
[manager POST:@”” parameters:@”” progress:nil success:nil failure:nil];

今天遇到的問題是無論怎麼連結都是Bad Request(400),主要原因是參數不正確。再三確認過,確定參數無誤,不斷試錯結果發現可能是參數沒能正確傳遞到後台導致判斷參數不正確(根本沒接收到)。

加上這次測試的後台環境比較特(ㄑ一ˊ)殊(ㄍㄨㄞˋ),需要透過header傳參數還加上透過http body傳參數,在Google許久後發現點蛛絲馬跡。重點在於[request setHTTPBody:data];

在AFNetworking 2.x時代是可以這樣做的:

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]]; 
[request setHTTPMethod:@”POST”];
[request setValue:@”application/json” forHTTPHeaderField:@”Content-Type”];
NSError *error; 
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; // And finally, add it to HTTP body and job done. 
[request setHTTPBody:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; manager.requestSerializer.timeoutInterval=[[[NSUserDefaults standardUserDefaults] valueForKey:@”timeoutInterval”] longValue]; manager.requestSerializer = [AFJSONRequestSerializer serializer]; AFHTTPRequestOperation *operation = [manager HTTPRequestOperationWithRequest:request progress:nil success:^(NSURLSessionTask *task, id responseObject) { NSLog(@”Reply JSON: %@”, responseObject); } } failure:^(NSURLSessionTask *operation, NSError *error) { NSLog(@”Error: %@, %@, %@, %@, %@”, error, operation.responseObject, operation.responseData, operation.responseString, operation.request); }]; 
[operation start];

但是AFNetworking 3.0以後棄用了AFHTTPRequestOperationManager,那怎麼才能用呢?

方法有兩種:

1.使用原生連線物件NSURLConnection或是NSURLSession

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@”url”]]; [request setHTTPBody:data]; [request setHTTPMethod:@”POST”]; [request setValue:@”application/json” forHTTPHeaderField:@”Content-Type”]; NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];

2.使用AFNetworking 3.0(一般來AFURLSessionManager)

AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; NSMutableURLRequest *req = [[AFJSONRequestSerializer serializer] requestWithMethod:@”POST” URLString:@”url” parameters:nil error:nil]; req.timeoutInterval= [[[NSUserDefaults standardUserDefaults] valueForKey:@”timeoutInterval”] longValue]; [req setValue:@”application/json” forHTTPHeaderField:@”Content-Type”]; [req setValue:@”application/json” forHTTPHeaderField:@”Accept”]; [req setHTTPBody:data]; [[manager dataTaskWithRequest:req completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { if (!error) { NSLog(@”Reply JSON: %@”, responseObject); } else { NSLog(@”Error: %@, %@, %@”, error, response, responseObject); } }] resume];

重點一樣擺在 [req setHTTPBody:postBodyData];

NSMutableData *postBodyData = [NSMutableData data];
[postBodyData appendData:[@”key=value” dataUsingEncoding:NSUTF8StringEncoding]];
Like what you read? Give YuChun Lin a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.