1 概述
AFHTTPSessionManager
是AFURLSessionManager
的子類丢氢。我們可以通過(guò)這個(gè)類做HTTP請(qǐng)求聊记。其實(shí)整個(gè)AFHTTPSessionManager
邏輯很簡(jiǎn)單,只是用HTTP的方式拼接了請(qǐng)求召娜,并且調(diào)用父類的方式做處理运褪。我會(huì)通過(guò)AFHTTPSessionManager
api來(lái)講一下POST上傳數(shù)據(jù)的幾種基本格式,然后我再隨便分析一下AFHTTPSessionManager
。
2 POST請(qǐng)求的常用格式
HTTP/1.1協(xié)議規(guī)定的HTTP請(qǐng)求方法有OPTIONS玖瘸、GET秸讹、HEAD、POST雅倒、PUT璃诀、DELETE、TRACE蔑匣、CONNECT 這幾種劣欢。其中POST一般用來(lái)向服務(wù)端提交數(shù)據(jù),接下來(lái)要討論P(yáng)OST提交數(shù)據(jù)的幾種方式裁良。協(xié)議規(guī)定POST提交的數(shù)據(jù)必須放在消息主體中凿将,但協(xié)議并沒(méi)有規(guī)定數(shù)據(jù)必須使用什么編碼方式。實(shí)際上价脾,開(kāi)發(fā)者完全可以自己決定消息主體的格式牧抵,只要最后發(fā)送的 HTTP 請(qǐng)求滿足上面的格式就可以。
但是侨把,數(shù)據(jù)發(fā)送出去犀变,還要服務(wù)端解析成功才有意義妹孙。一般服務(wù)端語(yǔ)言如php、python等弛作,以及它們的framework涕蜂,都內(nèi)置了自動(dòng)解析常見(jiàn)數(shù)據(jù)格式的功能。服務(wù)端通常是根據(jù)請(qǐng)求頭(headers)中的Content-Type字段來(lái)獲知請(qǐng)求中的消息主體是用何種方式編碼映琳,再對(duì)主體進(jìn)行解析机隙。所以說(shuō)到POST提交數(shù)據(jù)方案,包含了Content-Type和消息主體編碼方式兩部分萨西。
2.1 application/x-www-form-urlencoded格式的POST請(qǐng)求
這應(yīng)該是最常見(jiàn)的 POST 提交數(shù)據(jù)的方式了有鹿。瀏覽器的原生表單,如果不設(shè)置enctype屬性谎脯,那么最終就會(huì)以application/x-www-form-urlencoded方式提交數(shù)據(jù)葱跋。Content-Type被指定為application/x-www-form-urlencoded,提交的數(shù)據(jù)按照 key1=val1&key2=val2的方式進(jìn)行編碼源梭,key和val都進(jìn)行了URL轉(zhuǎn)碼娱俺。
下面這個(gè)請(qǐng)求是簡(jiǎn)書進(jìn)入一篇文章頁(yè)面的時(shí)候,會(huì)自動(dòng)往服務(wù)器POST一個(gè)請(qǐng)求废麻,估計(jì)是統(tǒng)計(jì)文章被閱讀的次數(shù)等功能荠卷。具體看下面:
//發(fā)送的請(qǐng)求,刪除了cookie相關(guān)的部分
POST /notes/e15592ce40ae/mark_viewed.json HTTP/1.1
Host: www.reibang.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:52.0) Gecko/20100101 Firefox/52.0
Accept: */*
Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
X-CSRF-Token: vJvptva4Tqou/V3dd3nFCrcvRsb78FReHuIYZke5PVAnfR/tIAAMCfuaB2Z2/gaEohIZAsiEksUYyPqzg3DpSA==
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://www.reibang.com/p/e15592ce40ae
Content-Length: 98
Connection: keep-alive
Cache-Control: max-age=0
//請(qǐng)求體
uuid=4e3abc0f-1824-4a5d-982f-7d9dee92d9cd&referrer=http%3A%2F%2Fwww.reibang.com%2Fu%2Fad726ba6935d
用AFHTTPSessionManager
實(shí)現(xiàn)上面這個(gè)application/x-www-form-urlencoded
請(qǐng)求烛愧。
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSDictionary *params = @{
@"uuid":@"4e3abc0f-1824-4a5d-982f-7d9dee92d9cd",
@"referrer":@"http://www.reibang.com/p/e15592ce40ae"
};
NSURLSessionDataTask *task = [manager POST:@"http://www.reibang.com//notes/e15592ce40ae/mark_viewed.json" parameters:params progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"進(jìn)度更新");
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"返回?cái)?shù)據(jù):%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"返回錯(cuò)誤:%@",error);
}];
[task resume];
2.2 multipart/form-data格式的POST請(qǐng)求
Multipart/form-data的基礎(chǔ)方法是POST , 也就是說(shuō)是由POST方法來(lái)組合實(shí)現(xiàn)的.
Multipart/form-data與POST方法的不同之處在于請(qǐng)求頭和請(qǐng)求體.
Multipart/form-data的請(qǐng)求頭必須包含一個(gè)特殊的頭信息 : Content-Type , 且其值也必須規(guī)定為multipart/form-data , 同時(shí)還需要規(guī)定一個(gè)內(nèi)容分割符用于分割請(qǐng)求體中的多個(gè)POST的內(nèi)容 , 如文件內(nèi)容和文本內(nèi)容自然需要分割開(kāi)來(lái) , 不然接收方就無(wú)法正常解析和還原這個(gè)文件了.
Multipart/form-data的請(qǐng)求體也是一個(gè)字符串 , 不過(guò)和post的請(qǐng)求體不同的是它的構(gòu)造方式 , post是簡(jiǎn)單的name=value值連接 , 而Multipart/form-data則是添加了分隔符等內(nèi)容的構(gòu)造體.
請(qǐng)求的頭部信息如下:
//其中xxxxx是我自定義的分隔符油宜,每個(gè)人都可以選擇自己的分隔符
Content-Type: multipart/form-data; boundary=xxxxx
下面我們來(lái)看一下一個(gè)我的Multipart/form-data請(qǐng)求體:
POST /uploadFile HTTP/1.1
Host: 這里是url,就不暴露了^_^
Content-Type: multipart/form-data; boundary=xxxxx
Connection: keep-alive
Accept: */*
User-Agent: AFNetWorking3.X%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/1 CFNetwork/808.2.16 Darwin/15.6.0
Content-Length: 32175
Accept-Language: en-us
Accept-Encoding: gzip, deflate
--xxxxx
Content-Disposition: form-data;name="file"
img.jpeg
--xxxxx
Content-Disposition: form-data;name="businessType"
CC_USER_CENTER
--xxxxx
Content-Disposition: form-data;name="fileType"
image
--xxxxx
Content-Disposition:form-data;name="file";filename="img1.jpeg"
Content-Type:image/png
這里是圖片數(shù)據(jù),太長(zhǎng)了.我就刪了
--xxxxx--
這個(gè)請(qǐng)求有三個(gè)參數(shù)file
,businessType
,fileType
。比如file
參數(shù)和他的值就通過(guò)如下格式傳輸:
--xxxxx
Content-Disposition: form-data;name="file"
img.jpeg
上面這種就是一個(gè)參數(shù)與之對(duì)應(yīng)的值怜姿。協(xié)議規(guī)定的就是這個(gè)格式慎冤,沒(méi)有為什么。我們可以看看圖片數(shù)據(jù)部分:
--xxxxx
Content-Disposition:form-data;name="file";filename="img1.jpeg"
Content-Type:image/png
這里是圖片數(shù)據(jù),太長(zhǎng)了.我就刪了
--xxxxx--
其中name="參數(shù)名" filename="文件名" 其中參數(shù)名這個(gè)要和接收方那邊相對(duì)應(yīng) 正常開(kāi)發(fā)中可以去問(wèn)服務(wù)器那邊 , 文件名是說(shuō)在服務(wù)器端保存成文件的名字 , 這個(gè)參數(shù)然并卵 , 因?yàn)橐话惴?wù)端會(huì)按照他們自己的要求去處理文件的存儲(chǔ).
下一行是指定類型 , 我這里示例中寫的是PNG圖片類型 , 這個(gè)可以根據(jù)你的實(shí)際需求的寫沧卢。如果我們要上傳多分圖片或者文件蚁堤,則只需要按照指定格式就可以了,比如下面就是上傳兩張圖片的請(qǐng)求:
POST /uploadFile HTTP/1.1
Host: 這里是url,就不暴露了^_^
Content-Type: multipart/form-data; boundary=xxxxx
Connection: keep-alive
Accept: */*
User-Agent: AFNetWorking3.X%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/1 CFNetwork/808.2.16 Darwin/15.6.0
Content-Length: 32175
Accept-Language: en-us
Accept-Encoding: gzip, deflate
--xxxxx
Content-Disposition: form-data;name="file"
img.jpeg
--xxxxx
Content-Disposition: form-data;name="businessType"
CC_USER_CENTER
--xxxxx
Content-Disposition: form-data;name="fileType"
image
--xxxxx
Content-Disposition:form-data;name="file";filename="img1.jpeg"
Content-Type:image/png
這里是圖片1數(shù)據(jù),太長(zhǎng)了.我就刪了
--xxxxx
Content-Disposition:form-data;name="file";filename="img2.jpeg"
Content-Type:image/png
這里是圖片1數(shù)據(jù),太長(zhǎng)了.我就刪了
--xxxxx--
下面是我Demo中一個(gè)multipart/form-data
請(qǐng)求的實(shí)現(xiàn)代碼,分別用NSRULDataTask
和AFHTTPSessionManager
實(shí)現(xiàn),我們可以發(fā)現(xiàn)用第二種方法簡(jiǎn)便了很多但狭,因?yàn)锳FN已經(jīng)幫我們做好了拼接工作:
//方法一
- (IBAction)updatePic:(id)sender {
//請(qǐng)求頭參數(shù)
NSDictionary *dic = @{
@"businessType":@"CC_USER_CENTER",
@"fileType":@"image",
@"file":@"img.jpeg"
};
//請(qǐng)求體圖片數(shù)據(jù)
NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:@"1.png"]);
//創(chuàng)建request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:url]];
//post方法
[request setHTTPMethod:@"POST"];
// 設(shè)置請(qǐng)求頭格式為Content-Type:multipart/form-data; boundary=xxxxx
//[request setValue:@"multipart/form-data; boundary=xxxxx" forHTTPHeaderField:@"Content-Type"];
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionDataTask *task = [manager POST:url parameters:dic constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
//請(qǐng)求體里面的參數(shù)
NSDictionary *bodyDic = @{
@"Content-Disposition":@"form-data;name=\"file\";filename=\"img.jpeg\"",
@"Content-Type":@"image/png",
};
[formData appendPartWithHeaders:bodyDic body:imageData];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"下載進(jìn)度");
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"下載成功:%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"下載失敗%@",error);
}];
[task resume];
}
//方法二
- (IBAction)multipartformPost2:(id)sender {
//參數(shù)
NSDictionary *dic = @{
@"businessType":@"CC_USER_CENTER",
@"fileType":@"image",
@"file":@"img.jpeg"
};
NSString *boundaryString = @"xxxxx";
NSMutableString *str = [NSMutableString string];
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
[str appendFormat:@"--%@\r\n",boundaryString];
[str appendFormat:@"%@name=\"%@\"\r\n\r\n",@"Content-Disposition: form-data;",key];
[str appendFormat:@"%@\r\n",obj];
}];
NSMutableData *requestMutableData=[NSMutableData data];
[str appendFormat:@"--%@\r\n",boundaryString];
[str appendFormat:@"%@:%@",@"Content-Disposition",@"form-data;"];
[str appendFormat:@"%@=\"%@\";",@"name",@"file"];
[str appendFormat:@"%@=\"%@\"\r\n",@"filename",@"img1.jpeg"];
[str appendFormat:@"%@:%@\r\n\r\n",@"Content-Type",@"image/png"];
//轉(zhuǎn)換成為二進(jìn)制數(shù)據(jù)
[requestMutableData appendData:[str dataUsingEncoding:NSUTF8StringEncoding]];
NSData *imageData = UIImagePNGRepresentation([UIImage imageNamed:@"1.png"]);
//文件數(shù)據(jù)部分
[requestMutableData appendData:imageData];
//添加結(jié)尾boundary
[requestMutableData appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n",boundaryString] dataUsingEncoding:NSUTF8StringEncoding]];
//創(chuàng)建一個(gè)請(qǐng)求對(duì)象
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:url]];
//post方法
[request setHTTPMethod:@"POST"];
// 設(shè)置請(qǐng)求頭格式為Content-Type:multipart/form-data; boundary=xxxxx
[request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundaryString] forHTTPHeaderField:@"Content-Type"];
//session
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionDataTask *task = [session uploadTaskWithRequest:request fromData:requestMutableData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",result);
}];
[task resume];
}
Multipart/form-data
格式的POST請(qǐng)求總結(jié):
- 文件類型參數(shù)中
name="參數(shù)名"
一定要和服務(wù)端對(duì)應(yīng), 開(kāi)發(fā)的時(shí)候 , 可以問(wèn)服務(wù)端人員披诗,我這里是file
。 - 上傳文件的數(shù)據(jù)部分使用二進(jìn)制數(shù)據(jù)
(NSData)
拼接熟空。 - 上邊界部分和下邊界部分的字符串 , 最后都要轉(zhuǎn)換成二進(jìn)制數(shù)據(jù)(NSData) , 和文件部分的二進(jìn)制數(shù)據(jù)拼接在一起 , 作為請(qǐng)求體發(fā)送給服務(wù)器。
- 每一行末尾需要有一定的`\r\n·搞莺。
2.3 application/json格式的POST請(qǐng)求
接下來(lái)我將常使用NSURLSessionDataTask
做一個(gè)application/json
的POST請(qǐng)求息罗。并且請(qǐng)求體數(shù)據(jù)我存儲(chǔ)在一個(gè)test.txt
文件中,從文件中讀取出來(lái)然后上傳才沧。
//test.txt文件內(nèi)容
{"name":"huang","phone":"124"}
通過(guò)抓包軟件我的請(qǐng)求如下迈喉,和其他POST請(qǐng)求原理一樣绍刮,只是拼接請(qǐng)求體的方式不一樣,并且更具不同格式的請(qǐng)求體挨摸,設(shè)置不同的Content-Type
:
POST /posts HTTP/1.1
Host: jsonplaceholder.typicode.com
Content-Type: application/json
Connection: keep-alive
Accept: application/json
User-Agent: AFNetWorking3.X%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB/1 CFNetwork/808.2.16 Darwin/15.6.0
Content-Length: 31
Accept-Language: en-us
Accept-Encoding: gzip, deflate
{"name":"huang","phone":"124"}
下面是我Demo的具體實(shí)現(xiàn)
- (IBAction)applicationjsonPOST2:(id)sender {
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://jsonplaceholder.typicode.com/posts"]];
//指請(qǐng)求體的類型孩革。由于我們test.txt里面的文件是json格式的字符串。所以我這里指定為`application/json`
[request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request addValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPMethod:@"POST"];
[request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
[request setTimeoutInterval:20];
NSString *path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"txt"];
NSURL *url = [NSURL URLWithString:[path stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
//使用Block來(lái)處理返回?cái)?shù)據(jù)
NSURLSessionDataTask *task = [session uploadTaskWithRequest:request fromFile:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",result);
}];
[task resume];
}
AFHTTPSessionManager分析
上面主要講了對(duì)POST請(qǐng)求的分析得运,主要是AFHTTPSessionManager
并沒(méi)有多少邏輯,他主要是調(diào)用AFURLSessionManager
的實(shí)現(xiàn)膝蜈。另外就是通過(guò)baseURL
改變了url的拼接過(guò)程。下面我就抽出他們的不同點(diǎn)分析一下:
1 首先多了一個(gè)屬性
@property (nonatomic, strong) AFHTTPRequestSerializer <AFURLRequestSerialization> * requestSerializer;
這個(gè)屬性的主要作用就是幫我們拼接請(qǐng)求頭和請(qǐng)求體熔掺,從上面的Demo我們發(fā)現(xiàn)很多請(qǐng)求的拼接工作都通過(guò)requestSerializer
處理了饱搏。如果我們不手動(dòng)設(shè)置,默認(rèn)是一個(gè)AFHTTPRequestSerializer
對(duì)象置逻。具體可以去初始化方法里面看到推沸。
2 重寫了securityPolicy
這個(gè)屬性的setter
方法,增加對(duì)于SSLPinningMode
的異常處理。
- (void)setSecurityPolicy:(AFSecurityPolicy *)securityPolicy {
//增加對(duì)于SSLPinningMode的異常處理券坞。
if (securityPolicy.SSLPinningMode != AFSSLPinningModeNone && ![self.baseURL.scheme isEqualToString:@"https"]) {
NSString *pinningMode = @"Unknown Pinning Mode";
switch (securityPolicy.SSLPinningMode) {
case AFSSLPinningModeNone: pinningMode = @"AFSSLPinningModeNone"; break;
case AFSSLPinningModeCertificate: pinningMode = @"AFSSLPinningModeCertificate"; break;
case AFSSLPinningModePublicKey: pinningMode = @"AFSSLPinningModePublicKey"; break;
}
NSString *reason = [NSString stringWithFormat:@"A security policy configured with `%@` can only be applied on a manager with a secure base URL (i.e. https)", pinningMode];
@throw [NSException exceptionWithName:@"Invalid Security Policy" reason:reason userInfo:nil];
}
//調(diào)用`AFURLSessionManager`的`securityPolicy`屬性的setter方法鬓催。
[super setSecurityPolicy:securityPolicy];
}
3 NSCopying和NSSecureCoding協(xié)議的實(shí)現(xiàn)過(guò)程
NSCopying
和NSSecureCoding
協(xié)議的實(shí)現(xiàn)過(guò)程添加了對(duì)requestSerializer
,responseSerializer
,securityPolicy
這三個(gè)屬性的復(fù)制。也就是說(shuō)恨锚,用copy方法復(fù)制的manager宇驾,這三個(gè)屬性的配置跟著一起復(fù)制。而父類AFURSSessionManager
只實(shí)現(xiàn)了對(duì)configuration
的復(fù)制眠冈。
+ (BOOL)supportsSecureCoding {
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)decoder {
NSURL *baseURL = [decoder decodeObjectOfClass:[NSURL class] forKey:NSStringFromSelector(@selector(baseURL))];
//獲取當(dāng)前manager的NSURLSessionConfiguration
NSURLSessionConfiguration *configuration = [decoder decodeObjectOfClass:[NSURLSessionConfiguration class] forKey:@"sessionConfiguration"];
if (!configuration) {
NSString *configurationIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"identifier"];
if (configurationIdentifier) {
//iOS7和iOS8初始化NSURLSessionConfiguration方法不一樣飞苇。所以要分開(kāi)處理
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1100)
configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:configurationIdentifier];
#else
configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:configurationIdentifier];
#endif
}
}
//初始化一個(gè)新的manager
self = [self initWithBaseURL:baseURL sessionConfiguration:configuration];
if (!self) {
return nil;
}
//添加了對(duì)`requestSerializer`,`responseSerializer`,`securityPolicy`這三個(gè)屬性的接檔。
self.requestSerializer = [decoder decodeObjectOfClass:[AFHTTPRequestSerializer class] forKey:NSStringFromSelector(@selector(requestSerializer))];
self.responseSerializer = [decoder decodeObjectOfClass:[AFHTTPResponseSerializer class] forKey:NSStringFromSelector(@selector(responseSerializer))];
AFSecurityPolicy *decodedPolicy = [decoder decodeObjectOfClass:[AFSecurityPolicy class] forKey:NSStringFromSelector(@selector(securityPolicy))];
if (decodedPolicy) {
self.securityPolicy = decodedPolicy;
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[super encodeWithCoder:coder];
//添加對(duì)baseURL屬性的歸檔
[coder encodeObject:self.baseURL forKey:NSStringFromSelector(@selector(baseURL))];
if ([self.session.configuration conformsToProtocol:@protocol(NSCoding)]) {
[coder encodeObject:self.session.configuration forKey:@"sessionConfiguration"];
} else {
[coder encodeObject:self.session.configuration.identifier forKey:@"identifier"];
}
//添加了對(duì)`requestSerializer`,`responseSerializer`,`securityPolicy`這三個(gè)屬性的歸檔蜗顽。
[coder encodeObject:self.requestSerializer forKey:NSStringFromSelector(@selector(requestSerializer))];
[coder encodeObject:self.responseSerializer forKey:NSStringFromSelector(@selector(responseSerializer))];
[coder encodeObject:self.securityPolicy forKey:NSStringFromSelector(@selector(securityPolicy))];
}
#pragma mark - NSCopying
- (instancetype)copyWithZone:(NSZone *)zone {
AFHTTPSessionManager *HTTPClient = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL sessionConfiguration:self.session.configuration];
//添加了對(duì)`requestSerializer`,`responseSerializer`,`securityPolicy`這三個(gè)屬性的復(fù)制布卡。
HTTPClient.requestSerializer = [self.requestSerializer copyWithZone:zone];
HTTPClient.responseSerializer = [self.responseSerializer copyWithZone:zone];
HTTPClient.securityPolicy = [self.securityPolicy copyWithZone:zone];
return HTTPClient;
}
4 HEAD和PUT等方法的實(shí)現(xiàn)
我在這里不準(zhǔn)備深入講這兩個(gè)方法是如何實(shí)現(xiàn)的,因?yàn)?code>AFHTTPSessionManager主要通過(guò)他的requestSerializer
屬性來(lái)實(shí)現(xiàn)對(duì)HEAD
和PUT
等請(qǐng)求的拼接雇盖。我準(zhǔn)備分析AFHTTPRequestSerializer
的時(shí)候再看這一塊是如何實(shí)現(xiàn)的忿等。
//通過(guò)requestSerializer屬性來(lái)拼接request對(duì)象。
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];