如何使用 AFNetwork 的 AFHTTPRequestOperationManager 设置 HTTP 请求正文?
Posted
技术标签:
【中文标题】如何使用 AFNetwork 的 AFHTTPRequestOperationManager 设置 HTTP 请求正文?【英文标题】:How to set HTTP request body using AFNetwork's AFHTTPRequestOperationManager? 【发布时间】:2013-10-31 17:05:06 【问题描述】:我正在使用 AFHTTPRequestOperationManager(2.0 AFNetworking 库)进行 REST POST 请求。但经理只有设置参数的调用。
-((AFHTTPRequestOperation *)POST:(NSString *)URLString
parameters:(NSDictionary *)parameters
success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure;
我还需要使用字符串设置 HTTP 请求正文。我怎样才能使用 AFHTTPRequestOperationManager 来做到这一点?谢谢。
【问题讨论】:
【参考方案1】:我遇到了同样的问题,通过添加代码解决了它,如下所示:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL
cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10];
[request setHTTPMethod:@"POST"];
[request setValue:@"Basic: someValue" forHTTPHeaderField:@"Authorization"];
[request setValue: @"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody: [body dataUsingEncoding:NSUTF8StringEncoding]];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer = [AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
NSLog(@"JSON responseObject: %@ ",responseObject);
failure:^(AFHTTPRequestOperation *operation, NSError *error)
NSLog(@"Error: %@", [error localizedDescription]);
];
[op start];
【讨论】:
但是AFHTTPRequestOperationManager
怎么办?【参考方案2】:
对于 AFHTTPRequestOperationManager
[requestOperationManager.requestSerializer setValue:@"your Content Type" forHTTPHeaderField:@"Content-Type"];
[requestOperationManager.requestSerializer setValue:@"no-cache" forHTTPHeaderField:@"Cache-Control"];
// Fill parameters
NSDictionary *parameters = @@"name" : @"John",
@"lastName" : @"McClane";
// Customizing serialization. Be careful, not work without parametersDictionary
[requestOperationManager.requestSerializer setQueryStringSerializationWithBlock:^NSString *(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error)
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
NSString *argString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
return argString;
];
[requestOperationManager POST:urlString parameters:parameters timeoutInterval:kRequestTimeoutInterval success:^(AFHTTPRequestOperation *operation, id responseObject)
if (success)
success(responseObject);
failure:^(AFHTTPRequestOperation *operation, NSError *error)
if (failure)
failure(error);
];
【讨论】:
【参考方案3】:检查该便捷方法 (POST:parameters:success:failure) 在后台执行的操作并自己执行以访问实际的 NSMutableRequest 对象。
我使用的是 AFHTTPSessionManager 而不是 AFHTTPRequestOperation 但我想机制是相似的。
这是我的解决方案:
设置会话管理器(标头等)
手动创建 NSMutable 请求并添加我的 HTTPBody,基本上是在该便捷方法中复制粘贴代码。看起来像这样:
NSMutableURLRequest *request = [manager.requestSerializer requestWithMethod:@"POST" URLString:[[NSURL URLWithString:<url string>] absoluteString] parameters:parameters];
[request setHTTPBody:[self.POSTHttpBody dataUsingEncoding:NSUTF8StringEncoding]];
__block NSURLSessionDataTask *task = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error)
if (error)
// error handling
else
// success
];
[task resume];
【讨论】:
【参考方案4】:如果您深入研究 AFNetworking 的来源,您会发现在 POST
的情况下,方法参数被设置到您的 HTTP 请求的正文中。
每个键值字典对都以key1=value1&key2=value2
的形式添加到正文中。对由 & 符号分隔。
在 AFURLRequestSerialization.m 中搜索 application/x-www-form-urlencoded
。
如果字符串只是一个字符串,而不是键值对,那么您可以尝试使用AFQueryStringSerializationBlock
http://cocoadocs.org/docsets/AFNetworking/2.0.3/Classes/AFHTTPRequestSerializer.html#//api/name/setQueryStringSerializationWithBlock:但这只是我的猜测。
【讨论】:
【参考方案5】:您可以创建自己的 AFHTTPRequestSerializer
的自定义子类,并将其设置为您的 AFHTTPRequestOperationManager
的 requestSerializer。
在这个自定义 requestSerializer 中,你可以重写
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error;
在此方法的实现中,您将可以访问 NSURLRequest
,因此您可以执行类似的操作
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(id)parameters
error:(NSError *__autoreleasing *)error
NSURLRequest *serializedRequest = [super requestBySerializingRequest:request withParameters:parameters
error:error];
NSMutableURLRequest *mutableRequest = [serializedRequest mutableCopy];
// Set the appropriate content type
[mutableRequest setValue:@"text/xml" forHTTPHeaderField:@"Content-Type"];
// 'someString' could eg be passed through and parsed out of the 'parameters' value
NSData *httpBodyData = [someString dataUsingEncoding:NSUTF8StringEncoding];
[mutableRequest setHTTPBody:httpBodyData];
return mutableRequest;
您可以查看 AFJSONRequestSerializer
的实现,以获取设置自定义 HTTP 正文内容的示例。
【讨论】:
【参考方案6】:AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager POST:url parameters:jsonObject success:^(AFHTTPRequestOperation *operation, id responseObject)
//success
failure:^(AFHTTPRequestOperation *operation, NSError *error)
//fail
];
这是我找到的最好和最简洁的方法。
【讨论】:
这比其他方法简单得多。然而奇怪的是,这似乎不适用于 GET ... @Hampotato 通常,您的获取请求中不应包含正文。这是可能的,但不标准。 是的,我想通了。谢谢tdeegan! 这不是为了身体。【参考方案7】:也许我们可以使用 NSMutableURLRequest,这里是代码:
NSURL *url = [NSURL URLWithString:yourURLString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request setHTTPMethod:@"POST"];
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:parameters options:NSJSONWritingPrettyPrinted error:nil];
NSString *contentJSONString = [[NSString alloc] initWithData:JSONData encoding:NSUTF8StringEncoding];
[request setHTTPBody:[contentJSONString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
【讨论】:
以上是关于如何使用 AFNetwork 的 AFHTTPRequestOperationManager 设置 HTTP 请求正文?的主要内容,如果未能解决你的问题,请参考以下文章
我是不是需要将 Alamofire 请求打包成 AFNetwork 之类的东西?