AFNetworking3.0 & application/x-www-form-urlencoded

最近入职到新公司,公司后端要求POST用application/x-www-form-urlencoded作为提交数据的方式,而之前项目常用的AFNetworking默认是application/json,所以就需要自己动手做一点小的修改。
我们知道,以上两种方式都是常见的数据提交方式,只是不同的Content-Type对应各自格式的请求体,比如使用相同的参数

alpha = 1
bravo = 2
charlie = 3

分别以

application/x-www-form-urlencoded
multipart/form-data
application/json

请求同一个地址

http://192.168.1.1:8080/test/test

他们的请求头和请求体格式如下:

  1. application/x-www-form-urlencoded
  POST /test/test HTTP/1.1
  Host: 192.168.1.1:8080
  Content-Type: application/x-www-form-urlencoded
  Cache-Control: no-cache
  
  alpha=1&bravo=2&charlie=3
  1. multipart/form-data
  POST /test/test HTTP/1.1
  Host: 192.168.1.1:8080
  Cache-Control: no-cache
  Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW

  ------WebKitFormBoundary7MA4YWxkTrZu0gW
  Content-Disposition: form-data; name="alpha"

  1
  ------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="bravo"

  2
  ------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="charlie"

  3
------WebKitFormBoundary7MA4YWxkTrZu0gW--
  1. application/json
  POST /test/test HTTP/1.1
  Host: 192.168.1.1:8080
  Content-Type: application/json
  Cache-Control: no-cache
  
  {"alpha":"1","bravo":"2","charlie":"3"}

所以,不管后端怎么要求,只要我们最终提交的报文格式符合要求就可以完成请求。

回到正题,由于AF3.0及以上封装的最外层AFHTTPSessionManager的POST方法不能完成application/x-www-form-urlencoded的请求,但我们又不想完全放弃AF使用原生方法,那就只好往里面更深入一些,按照自己的需要作出一点深度定制。

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
                             parameters:(nullable id)parameters
                               progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
                                success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                                failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

首先以上AFHTTPSessionManager的方法不能继续使用了,我们要我们要自己初始化一个符合要求的Request,然后使用AFHTTPSessionManager的父类AFURLSessionManager中以下方法完成请求:

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler;

完整代码如下:

// 初始化Request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:15.0];

// http method
[request setHTTPMethod:@"POST"];
// http header
[request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
// http body
NSMutableString *paraString = [NSMutableString string];
for (NSString *key in [parameters allKeys]) {
    [paraString appendFormat:@"&%@=%@", key, parameters[key]];
}
[paraString deleteCharactersInRange:NSMakeRange(0, 1)]; // 删除多余的&号
[request setHTTPBody:[paraString dataUsingEncoding:NSUTF8StringEncoding]];

// 初始化AFManager
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration: [NSURLSessionConfiguration defaultSessionConfiguration]];
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
serializer.acceptableContentTypes = [NSSet setWithObjects:
                                     @"text/plain",
                                     @"application/json",
                                     @"text/html", nil];
manager.responseSerializer = serializer;

// 构建请求任务
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
    
    if (error) {
        // 请求失败
        NSLog(@"Request failed with reason '%@'", [error localizedDescription]);
    } else {
        // 请求成功
        NSLog(@"Request success with responseObject - \n '%@'", responseObject);
    }
}];

// 发起请求
[dataTask resume];

以上即为本次分享,如有描述不当或者其他问题,请交流指正。

你可能感兴趣的:(AFNetworking3.0 & application/x-www-form-urlencoded)