1、创建和运行请求
创建一个同步请求
这是最简单的用法,发送 startSynchronous 消息将在相同线程中执行请求,不管是否成功,完成后返回控制。
查看error属性以检测问题。
要以字符串形式得到响应,就调用responseString方法。这个方法不适合二进制数据 - 你应该使用responseData 得到NSData对象,或者如果有更大的文件,你可以设置downloadDestinationPath将请求下载到文件。
- (IBAction)grabURL:(id)sender {
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSString *response = [request responseString];
}
}
注意:一般的,你应该优先使用异步请求,如果你在主线程中使用ASIHTTPRequest的同步方法,程序的ui在请求过程中将被锁定而无法响应。
2、创建一个异步请求
下面的代码做同样的事情,但请求运行于后台。
- (IBAction)grabURLInBackground:(id)sender {
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request {
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
}
注意我们设置请求的委托,这样就能在请求完成或失败时得到通知。
这是创建异步请求最简单的方式,他会运行于场景后面的一个全局的NSOperationQueue中,对于更复杂的操作,例如在多个请求中追踪进展,你可能想要创建自己的队列,下面我们谈谈这个。
3、使用程序块(blocks)
对于v1.8,我们可以在支持程序块的平台使用他们:
- (IBAction)grabURLInBackground:(id)sender {
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data
NSData *responseData = [request responseData];
}];
[request setFailedBlock:^{
NSError *error = [request error];
}];
[request startAsynchronous];
}
注意:在我们声明请求时,用到了__block限定语,这很重要!它告诉block不要保留请求,来防止一个保留循环(retain-cycle),因为请求总会保留block.
4、使用队列
这个例子做同样的事,不同的是,我们为自己的请求创建了NSOperationQueue。
使用一个NSOperationQueue或者ASINetworkQueue,你能更有效的控制异步请求。我们使用一个请求,只有一定数量的请求能同时 运行。如果你添加多于maxConcurrentOperationCount数量的请求,这些请求将等到其他请求完成后才会开始。
- (IBAction)grabURLInTheBackground:(id)sender {
if (![self queue]) {
[self setQueue:[[[NSOperationQueue alloc] init] autorelease]];
}
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[request setDidFinishSelector:@selector(requestDone:)];
[request setDidFailSelector:@selector(requestWentWrong:)];
[[self queue] addOperation:request];
//queue is an NSOperationQueue
}
- (void)requestDone:(ASIHTTPRequest *)request {
NSString *response = [request responseString];
}
- (void)requestWentWrong:(ASIHTTPRequest *)request {
NSError *error = [request error];
}
在上面的例子中,'queue'是控制器的一个保留的NSOperationQueue属性。
我们设置自定义的selector处理成功或失败的回调。如果你不设置这些,默认的requestFinished和requestFailed将被使用,就像在之前的例子中一样。
在委托方法中处理对歌请求的成功和失败
如果你需要处理许多不同类型的请求,你有几个选择:
1. 如果你的请求都属于一个大的范围,你又想区别他们,可以设置请求的userInfo字典属性,填入你的自定义数据,你就可以在委托方法中读取了。在更简单的用例中,你可以简单的设置tag属性。这些属性都是给你自己用的,不会发送到服务器。
2. 如果你处理完全不同的请求,为每个请求设置不同的 setDidFinishSelector / setDidFailSelector。
3. 对更复杂的情况,或者你想在后台解析响应数据,可以为每个请求类型创建一个ASIHTTPRequest的子类,然后重载requestFinished: 和 failWithError: 。
注意:最好避免在委托方法中,用url来区分不同的请求,因为url属性在重定向时会改变。如果你真的真的想用的话,请用[request originalURL] 代替,这个将总是记录第请求连接时的首个url。
5、关于ASINetworkQueues
ASINetworkQueues是NSOperationQueue,它提供了额外的功能。
它的主要目的是追踪整个队列上传或下载的进度。
ASINetworkQueues提供了一些额外的委托方法selector。
requestDidStartSelector
每当队列中的一个请求开始运行时调用。你可以使用这个作为didStartSelector的替代方法,为你加到队列的请求设置一个委托。
requestDidReceiveResponseHeadersSelector
每当队列中的一个请求从服务器得到响应头时调用。对于大的下载,这个 selector有时在请求实际完成前执行。
你可以使用它作为对didReceiveResponseHeadersSelector的替代。
requestDidFinishSelector
每当队列中的一个请求完成时调用。可以使用它作为对didFinishSelector的替代。
requestDidFailSelector
每当队列中的请求失败时调用,可作为didFailSelector的替代。
queueDidFinishSelector
当队列完成时调用,不管单个请求成功或失败。
使用以上selector,要将队列的委托,而不是请求的委托,设置到实现这些selector所代表的方法的控制器。
ASINetworkQueues工作起来和NSOperationQueues稍有不同,加到其中的请求不会立刻运行,当使用 ASINetworkQueue时,添加你想运行的所有请求,然后调用[queue go]。当你启动一个队列,将精确进度(accurate progress)打开时,他会首先为队列中所有的get请求执行一个head请求,来得到将要下载数据的总体尺寸。获得此数据后,它就能准确的显示总体 进度,然后真实的请求才会开始。
问题:当你向一个运行中的ASINetworkQueue加入一个请求时发生了什么事情?
回答:如果你使用ASINetworkQueue来追踪几个请求的总体进度,整体进度只会在哪个请求开始执行时,才会将它计算在内。 ASINetworkQueue不会在运行中,当加入请求后执行head请求,所以如果你立刻向运行的队列加入许多请求,总体进度不会立刻更新。
如果队列已经运行,你不需要再次调用[queue go]。
当ASINetworkQueue中的一个请求失败,队列默认的将取消所有其他的请求。你可以调用[queue setShouldCancelAllRequestsOnFailure:NO].来关闭这一行为。
ASINetworkQueues只能执行ASIHTTPRequest操作,而不能用于一般操作,尝试添加一个非ASIHTTPRequest的NSOperation将产生一个异常。
提示:这里有一个创建和使用ASINetworkQueue的完整例子:
http://gist.github.com/150447
6、取消一个异步请求
为了取消一个异步请求,可以调用[request cancel],不管该请求是用[request startAsynchronous] 启动的,还是在你创建的队列中运行。注意你不能取消一个同步请求。
注意,当你取消一个请求,请求会将之视为一个错误,然后会调用你的委托或者队列的失败委托方法。如果你不想这种事发生,在取消之前将委托设为nil,或者使用clearDelegatesAndCancel作为代替。
// Cancels an asynchronous request
[request cancel]
// Cancels an asynchronous request, clearing all delegates and blocks first
[request clearDelegatesAndCancel];
当使用一个ASINetworkQueue时,你取消其中一个请求,所有其他的请求也会被取消,除非队列的shouldCancelAllRequestsOnFailure为no, 默认为yes。
// When a request in this queue fails or is cancelled, other requests will continue to run
[queue setShouldCancelAllRequestsOnFailure:NO];
// Cancel all requests in a queue
[queue cancelAllOperations];
7、
安全处理委托在请求完成前释放的情况
请求不会保留他们的委托,所以如果你的委托有机会在请求运行时释放的话,你能及时清理请求的委托属性是至关重要的。在大多数情况下,如果你的委托将要释放,你大概也想取消请求,因为你不再关心请求的状态。
在下面的例子中,控制器有一个保存于保留实例变量中的ASIHTTPRequest对象。我们在其dealloc实现中调用clearDelegatesAndCancel方法,在我们释放请求的引用之前:
// Ddealloc method for our controller
- (void)dealloc {
[request clearDelegatesAndCancel];
[request release];
..
[super dealloc];
}
8、发送数据
发送请求头
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request addRequestHeader:@"Referer" value:@"http://allseeing-i.com/"];
用ASIFormDataRequest发送一个表单
要以兼容web页表单的方式发送post数据,可以使用ASIFormDataRequest的子类。数据以‘application/x-www- form-urlencoded’格式寄出,或者用‘multipart/form-data’格式上传二进制数据或文件。文件中的数据按照需要从磁盘读 取,所以发送大文件是没问题的,只要你的web服务器设置了如何处理他们。
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:@"Ben" forKey:@"first_name"];
[request setPostValue:@"Copsey" forKey:@"last_name"];
[request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];
ASIFormDataRequest使用setFile:forKey:添加文件时将自动侦测文件的mime类型(ios3.0之后),并包含这个到发送到服务器的mime头部中。如果你愿意,你可以使用更长的重载形式:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
// Upload a file on disk
[request setFile:@"/Users/ben/Desktop/ben.jpg" withFileName:@"myphoto.jpg" andContentType:@"image/jpeg"
forKey:@"photo"];
// Upload an NSData instance
[request setData:imageData withFileName:@"myphoto.jpg" andContentType:@"image/jpeg" forKey:@"photo"];
你可以为同一个参数发送多个值使用其他的add api:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request addPostValue:@"Ben" forKey:@"names"];
[request addPostValue:@"George" forKey:@"names"];
[request addFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photos"];
[request addData:imageData withFileName:@"george.jpg" andContentType:@"image/jpeg" forKey:@"photos"];
参考ASIFormDataRequest.h,了解添加到你post的参数的所有方法的完整列表。
9、put方法和自定义post
如果你想通过put发送数据,或者想要发送post,但是想自己创建post数据体(body),使用appendPostData: 或者 appendPostDataFromFile:。
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request appendPostData:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]];
// Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody:
[request setRequestMethod:@"PUT"];
如果你想发送大量的数据,并且不用ASIFormDataRequest,参看后面的‘从磁盘以流式post数据’小节。
10、下载数据
将响应数据直接下载为文件
如果你请求的数据相当大,你可以直接将下载内存直接保存为文件。这样,ASIHTTPRequest不需要一次在内存中保存整个请求。
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"];
当使用downloadDestinationPath下载到文件时,下载过程中,数据将被保存在一个临时文件中。这个文件路径保存于temporaryFileDownloadPath。当请求成功完成,下面的事情之一会发生:
如果数据时gzip压缩过的,压缩文件将被解压到downloadDestinationPath,并且临时文件被删除;
如果数据没被压缩,临时文件移动到downloadDestinationPath,覆盖掉任何之前的文件。
注意:如果响应body是空的,文件是不会被创建的。所以如果请求可能返回一个空的body,你要确定在尝试操作文件之前,检查它是否存在
11、处理收到的响应数据
如果你需要处理收到的响应数据,比如你想使用流解析器(streaming parser)来解析仍在下载的响应数据,就需要在委托中实现request:didReceiveData:方法。注意当你这么做 时,ASIHTTPRequest不会产生responseData,也不会将数据写入downloadDestinationPath - 你必须自己搞定保存响应数据的事。
读取HTTP状态码
ASIHTTPRequest 不会鸟大多数的http状态码,重定向和验证的状态码除外。所以,就要靠你检查问题,比如404错误,然后确定你做了恰当的处理。
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
int statusCode = [request responseStatusCode];
NSString *statusMessage = [request responseStatusMessage];
读取响应头
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSString *poweredBy = [[request responseHeaders] objectForKey:@"X-Powered-By"];
NSString *contentType = [[request responseHeaders] objectForKey:@"Content-Type"];
处理文本编码
ASIHTTPRequest会尝试从Content-Type头得到数据的编码。如果它发现了一个编码类型,他会社子responseEncoding 为相应的NSStringEncoding。如果它没在头部发现编码信息,就会用defaultResponseEncoding,这个值默认为 NSISOLatin1StringEncoding。
当你调用[request responseString],ASIHTTPRequest将尝试用responseEncoding作为源编码,从收到的数据创建一个字符串。
处理重定向
当ASIHTTPRequest碰到以下http状态码时,会自动重定向到一个新的url,假设Location头已经发送:
301 永久移动
302 发现
303 参看其他
当重定向发生,响应数据(responseHeaders / responseCookies / responseData / responseString 等) 的值将反映从最终位置收到的内容。
在重定向周期中碰到的任何url上设置的Cookie,都倍存储到全局cookie仓库,在恰当的时候会由重定向请求呈现给服务器。
你可以关闭自动重定向,设置shouldRedirect属性为no即可。
注意:默认情况下,自动重定向总是以get方式进行请求(没有body)。这个行为复合大多数的浏览器,除了象301和302这样应该用原有方式重定向的规范。
为了保留301和302的原有方式(包含请求的body),需要将shouldUseRFC2616RedirectBehaviour设置为yes,在你开始请求之前。
12、跟踪进度
每个ASIHTTPRequest都有两个用于跟踪进度的委托 - downloadProgressDelegate用于下载,uploadProgressDelegate用于上传。
进度委托可以是NSProgressIndicators(Mac OS X)或者UIProgressViews(iPhone)。ASIHTTPRequest会自动适应这两者行为上的差异。你也能够使用自定义的类作为进度 委托,只要它响应setProgress:方法。
如果你正执行单个请求,在这个请求上设置一个上传或下载委托。
如果你在队列中执行多个请求,并且想跟踪队列中所有请求的总体进度,可以使用ASINetworkQueue并设置队列的进度委托
如果想同时做上面两件事,也是可行的。
重点注意:如果你正在向需要验证的站点进行上传操作,为了提供有效验证,每当上传失败时,进度会被重设为之前的值。为此,如果你正同验证web服务器通 信,建议你仅当useSessionPersistence为yes时使用上传进度委托,并确保你在尝试跟踪大量上传数据前,在另一个请求中验证。
当请求body小于128kb时,目前是不能够跟踪上传进度的。对请求大于128kb的请求,进度委托不会收到第一个128kb的post数据进度的信息。这是因为CFNetwork API的限制造成的。
2009.6.21日更新:apple的好家伙非常友好的定位了我的bug报告!在iphone 2.0 sdk中,貌似这个缓冲尺寸减小到了32kb,这让精确的上传进度跟踪更加可靠了。
13、跟踪单个请求的下载进度
在这个例子中,myProgressIndicator是一个NSProgressIndicator。
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadProgressDelegate:myProgressIndicator];
[request startSynchronous];
NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);
跟踪一组请求的下载进度
这个例子中,myProgressIndicator 是一个UIProgressView,myQueue是一个ASINetworkQueue。
- (void)fetchThisURLFiveTimes:(NSURL *)url
{
[myQueue cancelAllOperations];
[myQueue setDownloadProgressDelegate:myProgressIndicator];
[myQueue setDelegate:self];
[myQueue setRequestDidFinishSelector:@selector(queueComplete:)];
int i;
for (i=0; i<5; i++) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[myQueue addOperation:request];
}
[myQueue go];
}
- (void)queueComplete:(ASINetworkQueue *)queue
{
NSLog(@"Value: %f", [myProgressIndicator progress]);
}
注意对于ASINetworkQueues,我们必须调用[myQueue go]来启动队列。
跟踪单个请求的上传进度
本例中,myProgressIndicator是一个UIProgressView。
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:@"Ben" forKey:@"first_name"];
[request setPostValue:@"Copsey" forKey:@"last_name"];
[request setUploadProgressDelegate:myProgressIndicator];
[request startSynchronous];
NSLog(@"Value: %f",[myProgressIndicator progress]);
跟踪一组请求的上传进度
本例中,myProgressIndicator是一个NSProgressUbdicator,myQueue是一个ASINetworkQueue。
- (void)uploadSomethingFiveTimes:(NSURL *)url
{
[myQueue cancelAllOperations];
[myQueue setUploadProgressDelegate:myProgressIndicator];
[myQueue setDelegate:self];
[myQueue setRequestDidFinishSelector:@selector(queueComplete:)];
int i;
for (i=0; i<5; i++) {
ASIHTTPRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostBody:[@"Some data" dataUsingEncoding:NSUTF8StringEncoding]];
[myQueue addOperation:request];
}
[myQueue go];
}
- (void)queueComplete:(ASINetworkQueue *)queue
{
NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);
}
14、
精确进度vs简单进度
ASIHTTPRequest提供了两种显示进度的途径,简单进度 和 精确进度。他们由ASIHTTPRequests 和 ASINetworkQueues的showAccurateProgress来控制。如果你在一个请求上设置 showAccurateProgress,只会影响这个请求。如果你设置了队列,将影响到队列的全部请求。
简单请求
当你使用简单进度,进度仅在请求完成时更新。对于单个进程,你只能得到0%和100%完成。对于一个包括4个请求的队列,你能得到5次进度更新,0%,25%,50%,75%和100%,每一次增量表明有一个请求完成了。
简单进度(showAccurateProgress = NO)是ASINetworkQueues的默认值,它很好的适用于包含大量的轻量级上传/下载请求的队列。
精确进度
使用精确进度时,进度以收发的字节来更新,所以极适合收发大量数据的请求,它会更好的指示一个耗时请求收发了多少数据。
使用精确进度会稍稍降低上传操作的性能,因为进度委托(可能是UIProgressView或者NSProgressIndicator)将更为频繁的重绘。
使用精确进度会对使用队列的下载任务影响更大,因为队列在下载前,会先为其中的get请求执行head请求,来决定将要下载的数据总体尺寸。强烈推荐你在队列中下载大文件时使用精确进度,但是应该避免队列中包含大量小型下载时使用它。
精确进度(showAccurateProgress = YES)是ASIHTTPRequests执行同步任务时的默认值。
15、自定义进度跟踪
ASIProgressDelegate协议定义了得到请求的更新进度的委托的所有方法。大多数情况下,为NSProgressIndicator或 UIProgressView设置uploadProgressDelegate 或 downloadProgressDelegate就足够了。但是,如果你想做更复杂的进度跟踪,你的进度委托应该优先于setProgress: (iOS) 或者setDoubleValue: / setsos5403: (Mac)实现下列方法。这些方法允许你得到收发的实际字节数,而不是更简单的方法得到的介于0和1之间的数字。
downloadProgressDelegates的方法
request:didReceiveBytes:每当请求下载更多数据时在downloadProgressDelegate上调用。注意这有别于一般会实现的request:didReceiveData:委托。
request:incrementDownloadSizeBy:下载尺寸改变时被调用,传入的参数是下载尺寸的增量。一般发生在请求收到响应头并获得了下载的尺寸时。
uploadProgressDelegates的方法
request:didSendBytes: 每当请求能发送一些数据时在uploadProgressDelegate上调用。重点提醒:这个方法能被小于0的数字调用,当一个请求需要删除上传进度 时(一般是当它已经上传了数据,但是验证失败或者由于某种原因需要再次运行时)。
request:incrementUploadSizeBy: 上传尺寸改变时调用。传入的尺寸经常会小于0,由于请求调整了上传尺寸,它将os内部的缓冲尺寸也计算在内了。
16、处理http验证
如果你正在连接到需要验证的服务器,你大概想要看看这个流程图
http://allseeing-i.com/ASIHTTPRe ... ticationProcess.pdf
,演示了ASIHTTPRequest如何找到和应用请求验证。
在url中指定用户名和密码
NSURL *url = [NSURL URLWithString:@"http://username:password@allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
设置请求的用户名和密码
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUsername:@"username"];
[request setPassword:@"password"];
17、在键链(keychain)中储存证书
如果你打开了keychainPersistence,任何你提供的有效用户名和密码将被存储到键链中。随后的请求会重用键链中的用户名和密码,即使你退出再重启应用。
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUseKeychainPersistence:YES];
[request setUsername:@"username"];
[request setPassword:@"password"];
如果你使用键链同时希望自己管理它,你应该能在ASIHTTPRequest.h中找到有助于此与键链相关的类方法。
18、在会话中保存证书
如果useSessionPersistence打开了,默认是打开的,ASIHTTPRequest将证书保存到内存,并可以在后续请求中重用他们。
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUsername:@"username"];
[request setPassword:@"password"];
[request setUseSessionPersistence:YES]; //Shouldn't be needed as this is the default
//Should reuse our username and password
request = [ASIHTTPRequest requestWithURL:url];
19、NTML验证
要通过使用ntml方案的windows服务器进行验证,你还需要指定你验证的域(domain)。
NSURL *url = [NSURL URLWithString:@"http://my.windows.server/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUsername:@"username"];
[request setPassword:@"password"];
[request setDomain:@"my-domain"];
使用委托来提供证书
相对于提前指定验证证书,你可能更愿意在请求不能从会话验证缓存或键链中得到证书时,向它的委托询问。这可能有助于你希望连到一个服务器,但你不确定它需要哪种类型的验证。
确定你的委托实现了authenticationNeededForRequest,ASIHTTPRequest会暂停一个请求,当它等待一个委托以获 得将要使用的证书时。当你有你需要的证书时,只要在请求上设置他们,然后调用[request retryUsingSuppliedCredentials],如果你想取消,就要调用[request cancelAuthentication],这也会取消请求。
对于v1.0.8,请求的委托一次只会收到一个authenticationNeededForRequest或者 proxyAuthenticationNeededForRequest。当委托处理第一个请求时,其他需要验证的请求会暂停执行。如果证书通过验证, 任何当前进程的其他请求都会尝试重用他们,假设他们对url有效。如果委托取消了验证,且队列的 shouldCancelAllRequestsOnFailure为yes,所有其他的请求不再尝试查询证书而会取消。
在使用同步请求时,你不能使用代理模式进行验证。
在老版本中这会导致应用挂起,对于v1.0.8代理方法不再被调用。
20、使用内置验证对话框(目前仅ios可用)
在v1.0.8中新增了ASIAuthenticationDialog类。它主要用来和验证代理一同工作,但是它可以被用来为验证web服务器询问用户的证书。
为了最好的用户体验,多数连到单个服务的应用应该在其委托中实现authenticationNeededForRequest:,或者避免完全的使用委 托样式(delegate-style)验证。但是有时为常规验证而使用ASIHTTPRequest的标准验证对话框有些好处:
你不想创建你自己的登录表单
你大概需要从外部来源获得数据,而不太确定它需不需要验证。
为此,在请求中设置shouldPresentAuthenticationDialog为true,如果你的委托没有实现authenticationNeededForRequest,用户将看到此对话框。
验证对话框不会在同步请求时出现。
对话框有点模仿了iphone上的safari,并包括:
一条消息指明这个认证是为web服务器做的(而不是代理)
你连接到的服务器的主机名或ip
验证域(authentication realm),如果支持的话
输入用户名和密码的文本框
当连接到一个使用ntlm方案的服务器时,对话框也包括一个输入域(domain)的文本框
关于验证是否以明文(plain text)发送的提示(仅在用无ssl的基本验证时才被明文发送)。
如果你想改变对话框的外观,子类化ASIHTTPRequest,重载showAuthenticationDialog来显示你自己的自定义对话框或者子类化ASIAuthenticationDialog。
21、在服务器要求之前提供证书
非常重要:在v1.0.8中,使用基本验证的请求时,这个特征改变了,你可能需要更新你的代码。
ASIHTTPRequest可以在首次请求时就为服务器提供证书,而不是等到服务器要求证书。结果是使用验证时获得更好的性能,因为它避免了额外的请求。
使用基本验证来触发此行为时,你应该手动设置请求的authenticationScheme:
[request setAuthenticationScheme:(NSString *)kCFHTTPAuthenticationSchemeBasic];
使用其他验证方案时,证书可以在服务器要求之前提供,但只有在另一个请求成功通过此服务器验证之后。
你可能希望禁用此特征,如果:
你的应用可能使用多组证书来同时和同一个服务器对话。
你的应用是安全至上的,使用这个特性本身不太安全,因为在你有机会验证你连接到你希望连接的服务器之前,证书已经被发送了。
为了禁用此特征,使用以下代码:
[request setShouldPresentCredentialsBeforeChallenge:NO];
22、Cookies
持久化cookies
ASIHTTPRequest允许你使用全局存储,全局存储为所有max os上使用CFNetwork或NSURLRequest API的应用所共享。如果useCookiePersistence为on(默认如此),cookies将被保存到共享的 NSHTTPCookieStorage容器中,并自动被其他请求自动重用。如果cookie仅对特定请求有效,ASIHTTPRequest提供其他程 序创建的cookie是没有价值的。
你可以象这样清除在会话中创建的所有cookie:
[ASIHTTPRequest setSessionCookies:nil];
这里,'会话cookie'指的一个会话中创建的所有cookie,而不是程序退出时被删除的无过期时间的cookie(经常被称为会话cookie)。
另外,类的方便(convenience)方法clearSession将清除所有会话中创建的cookie,以及任何缓存的验证数据。
手工处理cookie
如果你喜欢,你可以关掉useCookiePersistence,然后手动管理特定请求的一组cookie。
//Create a cookie
NSDictionary *properties = [[[NSMutableDictionary alloc] init] autorelease];
[properties setValue:[@"Test Value" encodedCookieValue] forKey:NSHTTPCookieValue];
[properties setValue:@"ASIHTTPRequestTestCookie" forKey:NSHTTPCookieName];
[properties setValue:@".allseeing-i.com" forKey:NSHTTPCookieDomain];
[properties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires];
[properties setValue:@"/asi-http-request/tests" forKey:NSHTTPCookiePath];
NSHTTPCookie *cookie = [[[NSHTTPCookie alloc] initWithProperties:properties] autorelease];
//This url will return the value of the 'ASIHTTPRequestTestCookie' cookie
url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"];
request = [ASIHTTPRequest requestWithURL:url];
[request setUseCookiePersistence:NO];
[request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request startSynchronous];
//Should be: I have 'Test Value' as the value of 'ASIHTTPRequestTestCookie'
NSLog(@"%@",[request responseString]);
23、处理压缩的响应,以及压缩请求body
使用gzip来处理压缩的响应数据
对于v0.9,ASIHTTPRequest不会提醒服务器它可以接受gzip压缩格式数据。如果你在现有项目中升级ASIHTTPRequest,参看设置指令地址
http://allseeing-i.com/ASIHTTPRequest/Setup-instructions
了解如何链接到zlib。
许多web服务器可以在发送数据前进行压缩 - 这样可以加快下载和降低使用带宽,代价是服务器(用以压缩数据)和客户端(解压数据)增加了额外的cpu时间。一般说来,只有某些类型的数据会被压缩 - 许多二进制格式例如jpeg,gif,png,swf和pdf已经压缩过他们的数据,所以gzip压缩不会用于发送他们到客户端。文本文件如网页和xml 文档是gzip压缩的完美候选人,因为他们经常包含大量重复信息。
如何设置apache使用mod_deflate来压缩数据
apatche 2.x 之后带来了mod_deflate扩展允许透明的压缩某些类型的数据。要打开他,你需要在apatche配置文件中启用mode_deflate,并添加mod_deflate指令到你的虚拟主机配置中,或者到你的.htaccess文件中。
在ASIHTTPRequest中使用gzip
- (IBAction)grabURL:(id)sender
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
// YES is the default, you can turn off gzip compression by setting this to NO
[request setAllowCompressedResponse:YES];
[request startSynchronous];
BOOL *dataWasCompressed = [request isResponseCompressed]; // Was the response gzip compressed?
NSData *compressedResponse = [request rawResponseData]; // Compressed data
NSData *uncompressedData = [request responseData]; // Uncompressed data
NSString *response = [request responseString]; // Uncompressed data as a string
}
当allowCompressedResponse为真,ASIHTTPRequest将添加Accept-Encoding头到请求中,表明我们可以接 受gzip压缩的响应数据。如果响应头包含一个content-encoding头指明了数据已被压缩,调用responseData 或者 responseString将在返回前解压数据。你可以通过调用rawResponseData得到原始压缩数据。
联机解压gzip响应包
默认的,ASIHTTPRequest会一直等到请求完成对gzip响应包的解压缩。设置 shouldWaitToInflateCompressedResponses属性为no,你可以告诉ASIHTTPRequest在收到数据同时进行 解压。有时候,这会提升一点速度,因为当一个请求等待更多响应时,数据可以同时被处理。
这个特性对于需要使用流解析器(streaming parser)如xml或json解析器时尤其有用,打开这个选项,你可以直接给你的解析器输送解压过的数据,他们来自你委托实现的request:didReceiveData: 方法。
注意当shouldWaitToInflateCompressedResponses为no时,原始(压缩过的)数据将被丢弃,参看ASIHTTPRequest.h的注释获得更多信息。
使用gzip来压缩请求body
v1.0.3新增了请求body的gzip压缩。使用这个特性,你的应用可以压缩post/put操作的内容,只要设置shouldCompressRequestBody为yes即可。shouldCompressRequestBody默认为no。
当你配置了SetInputFilter DEFLATE 后,apatche的mod_deflate可以自动的解压gzip请求体。这个方法为cgi内容工作,但是如果你使用apatche模块构建成了一个 RESOURCE过滤器(如mod PHP)则不能工作,这时你需要自己搞定数据解压。
注意:ASIHTTPRequest不能检查到服务器是否接受gzip请求体。只有当你确定服务器能搞定gzip body时使用这项特性。
避免对压缩格式文件如jpeg/png/gif/pdf/swf使用gzip,你会发现gzip版本会比原始文件大。
24、恢复被打断的下载
自v0.94开始,ASIHTTPRequest能够恢复不完整的下载
- (IBAction)resumeInterruptedDownload:(id)sender
{
NSURL *url = [NSURL URLWithString:
@"http://allseeing-i.com/ASIHTTPRequest/Tests/the_great_american_novel.txt"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
NSString *downloadPath = @"/Users/ben/Desktop/my_work_in_progress.txt";
// The full file will be moved here if and when the request completes successfully
[request setDownloadDestinationPath:downloadPath];
// This file has part of the download in it already
[request setTemporaryFileDownloadPath:@"/Users/ben/Desktop/my_work_in_progress.txt.download"];
[request setAllowResumeForFileDownloads:YES];
[request startSynchronous];
//The whole file should be here now.
NSString *theContent = [NSString stringWithContentsOfFile:downloadPath];
}
这只在下载数据到文件时有用,你必须设置allowResumeForFileDownloads为yes,为了:
任何你将来可能想恢复的下载(或者ASIHTTPRequest会在取消或释放时删除的临时下载)
任何你想恢复的下载
而且,你必须设置一个临时下载路径(setTemporaryFileDownloadPath),用不完整数据的路径,新数据将被追加到这个文件,当下载成功,这个文件会被移到downloadDestinationPath。
ASIHTTPRequest不会检查accept-range头(因为额外head请求的负担),所以仅在确定服务器能够支持不完整下载时才使用此特征。
25、直接从磁盘流式请求body
自v0.96开始,ASIHTTPRequest能够使用磁盘文件作为请求body。这意味着将请求body保持在内存不再必要,这样一来,大型的post/put操作的将极大的减少内存使用量。
你可以以几种方法来使用这一特征:
ASIFormDataRequests
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:@"foo" forKey:@"post_var"];
[request setFile:@"/Users/ben/Desktop/bigfile.txt" forKey:@"file"];
[request startSynchronous];
ASIFormDataRequests在你使用setFile:forKey:,自动使用这一特性。请求将创建临时文件,包含完整的请求body。文件 一次写入一些body的相关部分。请求被CFReadStreamCreateForStreamedHTTPRequest创建,使用此文件上的读取流 作为来源。
常规的ASIHTTPRequest
如果你知道你的请求将会很大,可以在请求上打开磁盘流(streaming from disk):
[request setShouldStreamPostDataFromDisk:YES];
在下面的例子中,我们每次添加一个NSData对象。有两个方法做这个事 - 从内存添加数据(appendPostData:),或者使用appendPostDataFromFile从文件添加内容。
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setShouldStreamPostDataFromDisk:YES];
[request appendPostData:myBigNSData];
[request appendPostDataFromFile:@"/Users/ben/Desktop/bigfile.txt"];
[request startSynchronous];
在本例中,我们想要直接put一个大文件。我们自己设置setPostBodyFilePath,ASIHTTPRequest将使用这个文件作为post body。
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setRequestMethod:@"PUT"];
[request setPostBodyFilePath:@"/Users/ben/Desktop/another-big-one.txt"];
[request setShouldStreamPostDataFromDisk:YES];
[request startSynchronous];
非常重要:你不应该在上面任何方法的同一个请求中使用setPostBody - 他们是互斥的,setPostBody只能用于你自己构建请求body,并计划将请求body保留到内存的情型。
26、使用下载缓存
ASIDownloadCache 以及 ASICacheDelegate 的API在v1.8中已经改变,如果从v1.7升级的话,你需要更新你的代码。
特别是,缓存策略的可用选项是不同的,并且你现在可以将多个缓存策略合并到单个请求中。
ASIHTTPRequest可以自动保存下载数据到一个缓存,以便以后使用。许多情况下这会很有帮助:
你想要访问数据,在没有因特网连接不能重新下载时;
你想下载些东西,仅在你上次下载后它有了变化时;
你用的内容永不改变,所以你只想下载它一次;
在之前的ASIHTTPRequest版本中,处理以上情况意味着你自己手动保存这些数据。使用一个下载缓存可以在一些情况下减少你自己编写本地存储机制的需求。
ASIDownloadCache是一个简单的url缓存,可以被用于缓存get请求的响应。为了符合响应缓存的条件,请求必须成功(没有错误),服务器 必须返回一个200 ok的http响应码,或者从v1.8.1开始,支持301,302,303,307重定向的状态码。
开启响应缓存很简单:
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
开启之后,所有的请求会自动使用缓存。如果你喜欢,你可以为独立的请求设置共享缓存:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
缓存不限于单个,你可以创建任意多个缓存。当你自己创建缓存时,必须设置缓存的存储路径 -这应该是一个可写的文件夹:
ASIDownloadCache *cache = [[[ASIDownloadCache alloc] init] autorelease];
[cache setStoragePath:@"/Users/ben/Documents/Cached-Downloads"];
// Don't forget - you are responsible for retaining your cache!
[self setMyCache:cache];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[self myCache]];
27、关于缓存策略
缓存策略是在信息存储于缓存中时你主要的控制方法,以及何时优先使用缓存的数据,而不是重新下载数据。
独立请求的缓存策略可以使用它的cachePolicy属性。缓存策略使用位掩码(bitmask)定义,所以你可以组合多个选项来创建想要的策略:
// Always ask the server if there is new content available,
// If the request fails, use data from the cache even if it should have expired.
[request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy];
你可以使用下列选项来定义一个请求的缓存策略:
ASIUseDefaultCachePolicy
默认缓存策略,当你对请求应用此策略时,它会使用缓存的defaultCachePolicy,ASIDownloadCache的默认缓存策略是 ASIAskServerIfModifiedWhenStaleCachePolicy,你不应该将此策略和其他策略组合使用。
ASIDoNotReadFromCacheCachePolicy
请求不会从缓存读取数据
ASIDoNotWriteToCacheCachePolicy
请求不会保存到缓存
ASIAskServerIfModifiedWhenStaleCachePolicy
这是ASIDownloadCaches的默认缓存策略。使用了它,请求会首先查看缓存中是否有可用的缓存响应数据。如果没有,请求会照常进行。
如果有没有过期的缓存数据,请求会使用它而不去访问服务器。如果缓存数据过期了,请求将执行一个有条件的get去获取是否有可用的升级版本。如果服务器表 示缓存的数据就是最新的,那么缓存的数据将被使用,新的数据不会被下载。这时,缓存的过期时间(expiry date)将根据服务器新的过期时间而被更新。如果服务器提供了更新内容,则将被下载,新的数据和过期时间将被写入缓存。
ASIAskServerIfModifiedCachePolicy
这个策略和ASIAskServerIfModifiedWhenStaleCachePolicy相同,只是请求每次都会询问服务器是否有新的数据
ASIOnlyLoadIfNotCachedCachePolicy
只要存在缓存数据,总是会被使用,即使它已经过期。
ASIDontLoadCachePolicy
请求仅在响应已经被缓存时成功。如果请求没有任何响应被缓存,请求会终止,并且也不会为此请求设置错误。
ASIFallbackToCacheIfLoadFailsCachePolicy
如果请求失败,将会退回到缓存数据。如果失败后使用了缓存的数据,请求将会成功而不报错。你一般会将它和其他策略混合使用,因为此策略仅在发生问题时用于指定行为。
当你为缓存设置了defaultCachePolicy属性,所有的请求将会使用这个缓存策略,除非他们自己设置了自定义的策略。
28、
关于存储策略
存储策略允许你定义特定响应的缓存将被保存多久,ASIHTTPRequest目前支持两种存储策略:
ASICacheForSessionDurationCacheStoragePolicy 是默认值。响应仅在会话期间被保存,并将在缓存首次使用后被删除,或者当调用[ASIHTTPRequest clearSession] 时被删除。
使用ASICachePermanentlyCacheStoragePolicy,缓存数据将被永久保存,要用这个存储策略,可将它设置到一个请求上:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
要手动清除缓存,调用clearCachedResponsesForStoragePolicy,传入你希望清除的缓存数据的存储类型:
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
29、其他缓存特性
// 当你关掉shouldRespectCacheControlHeaders, 响应数据将被保存,即使服务器明确要求不要缓存他们
// (eg with a cache-control or pragma: no-cache header)
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
为请求设置secondsToCache,覆盖了由服务器设置的任何过期时间,一直保存响应数据直到secondsToCache秒到期。
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setSecondsToCache:60*60*24*30]; // Cache for 30 days
在请求运行后,didUseCachedResponse将在响应由缓存返回时,返回yes
[request didUseCachedResponse];
询问缓存请求数据的保存路径,这是使用下载缓存最高效的方式,因为数据不必在请求完成后被拷贝到缓存
[request setDownloadDestinationPath:
[[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request]];
写你自己的缓存
如果你已经有一个下载缓存,并想将它接入到ASIHTTPRequest,或者你想要写自己的缓存,可以让你的缓存实现ASICacheDelegate协议。
30、节约带宽
从v1.0.7开始,ASIHTTPRequest能够限制所有请求使用的带宽,防止它超过一个用户定义的上限。这可以帮助收发大量数据的iphone应用通过app store的审核程序。
限流工作使用一个全局限制(以字节为单位),来限定每秒能够收发的数据总量。所有的请求共享这个限制。当他们收发数据时,ASIHTTPRequest追踪上一秒内有多少数据被收发。如果某个请求超过了限制,任何其他的执行单位也都必须等待本次测量时段结束。
在ios上,你可以让ASIHTTPRequest自动打开限流,当你使用一个wwan(gprs/edge/3g)连接时,而当切换到wifi时,会自动关闭他。
当使用wwan激活时将限制带宽到为移动应用预定义的默认值,wifi请求不受影响,此方法仅限于ios
// Will limit bandwidth to the predefined default for mobile applications when WWAN is active.
// Wi-Fi requests are not affected
// This method is only available on iOS
[ASIHTTPRequest setShouldThrottleBandwidthForWWAN:YES];
当wwan激活后,限制带宽为用户定义的值,仅限ios
// Will throttle bandwidth based on a user-defined limit when when WWAN (not Wi-Fi) is active
// This method is only available on iOS
[ASIHTTPRequest throttleBandwidthForWWANUsingLimit:14800];
限制所有请求,不管是不是wifi,都会限制到预定义的值--小心使用
// Will prevent requests from using more than the predefined limit for mobile applications.
// Will limit ALL requests, regardless of whether Wi-Fi is in use or not - USE WITH CAUTION
[ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount];
记录每秒多少字节的数据被收发(从前5秒取平均值)
// Log how many bytes have been received or sent per second (average from the last 5 seconds)
NSLog(@"%qi",[ASIHTTPRequest averageBandwidthUsedPerSecond]);
非常重要:启用带宽限制之前先读读这个:
带宽限制应被视为一个实验性特征,使用时自行承担风险
不要将带宽限制过底,最好不要低于ASIWWANBandwidthThrottleAmount
你的应用实际使用的带宽将总是稍稍大于你设置的值,因为带宽测量不包括http头使用的带宽
ASIWWANBandwidthThrottleAmount不是官方的值,据我所知,官方没有发布带宽限制值
你不应该在你的应用并没有大量数据传输时打开带宽限制,仅在有大量数据上传或下载的请求执行时启用它,其他时间请关闭。
31、客户端证书支持
如果你的服务器需要使用客户端证书,v1.8以后可以通过请求来发送他们。
// Will send the certificate attached to the identity (identity is a SecIdentityRef)
[request setClientCertificateIdentity:identity];
// Add an additional certificate (where cert is a SecCertificateRef)
[request setClientCertificates:[NSArray arrayWithObject:(id)cert]];
在iphone/ipad app的ClientCertificateTests.m中有一个帮助函数,可以从pkcs12数据创建一个SecIdentityRef(此函数仅在ios中有用)。
32、同代理一起工作
ASIHTTPRequest可以检测到系统代理并且自动将他们应用到请求。从v1.0.6开始,他也支持pac文件代理配置,以及验证代理。
默认的,ASIHTTPRequest将尝试自动检测代理设置,但是,你可能希望能够手动设置代理:
// Configure a proxy server manually
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setProxyHost:@"192.168.0.1"];
[request setProxyPort:3128];
// Alternatively, you can use a manually-specified Proxy Auto Config file (PAC)
// (It's probably best if you use a local file)
[request setPACurl:[NSURL URLWithString:@"file:///Users/ben/Desktop/test.pac"]];
验证代理
在mac os上,ASIHTTPRequest可以自动检测用于验证代理的证书,如果他们在系统参数中指定了的话。在ios上,则不能自动检测,所以你要么手动设 置他们,使用委托来询问控制器/相应证书的用户,要么让ASIAuthenticationDialog询问用户。一旦有效的代理证书被接受,他们将被保 存到键链中(当useKeychainPersistence被打开)并自动被重用。
手动指定代理的证书
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setProxyHost:@"192.168.0.1"];
[request setProxyPort:3128];
// Set a username and password for authenticating proxies
[request setProxyUsername:@"bencopsey"];
[request setProxyPassword:@"password"];
// For NTLM proxies, you can also set the domain (NTLM proxies are untested!)
[request setProxyDomain:@"la.la.land"];
使用委托来询问代理证书
这和使用委托提供常规验证证书的方式一样,除了委托必须响应proxyAuthenticationNeededForRequest(以前的名字是proxyAuthorizationNeededForRequest)。
使用内置验证对话框(目前仅ios)
v1.0.8之后新增了ASIAuthenticationDialog类。这个类可被用于询问用户web服务器或代理的验证证书。
如果你的委托不能响应proxyAuthenticationNeededForRequest,默认的,ASIHTTPRequest将显示一个提示用 户提供证书的对话框。它默认为代理服务器显示,这样所有使用ASIHTTPRequest的应用可以同验证代理工作,而不需要任何开发者端额外的努力。
同步请求时,代理验证对话框不会显示。
如果你不喜欢用代理验证对话框,要么你在你的代理中实现proxyAuthenticationNeededForRequest,或者将 shouldPresentProxyAuthenticationDialog设置为false(那样你的应用将不能连接到验证代理)。如果你想改变它 的外观,子类化ASIHTTPRequest并覆盖showProxyAuthenticationDialog来显示你的自定义对话框,或者子类化 ASIAuthenticationDialog。
33、其他特性
自定义用户代理
设置你的应用将使用的用户代理:
[ASIHTTPRequest setDefaultUserAgentString:@"MyApp 1.0"]
如果你不设置用户代理,ASIHTTPRequest会为你创建一个,例如(对于mac os 程序):
My Application 1.0 (Macintosh; Mac OS X 10.5.7; en_GB)
你也可以为每个请求设置用户代理:
[request setUserAgent:@"MyApp 1.0"]
在ios中程序进入后台时继续请求
// iOS 4+ only
[request setShouldContinueWhenAppEntersBackground:YES];
监视网络活动
// Log the average bandwidth used (in bytes) per second over the last 5 seconds
NSLog(@"%llu",[ASIHTTPRequest averageBandwidthUsedPerSecond]);
if ([ASIHTTPRequest isNetworkInUse]) {
// ASIHTTPRequest has requests in progress that are using the network
}
禁用自动更新网络活动指示器(仅ios)
默认的,ASIHTTPRequest会显示网络活动指示器(在状态条上),当你的请求使用网络时。如果你想要自己管理这个,你可以禁用这些更新:
[ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO];
当请求超时自动重试
请求超时,最多重试2次:
[request setNumberOfTimesToRetryOnTimeout:2];
配置持续连接(persistent connection)
默认的,ASIHTTPRequest将尝试保持到服务器的连接,这样他们可以被连到相同服务器的请求重用(这一般导致速度显著提升,特别是你有许多小的请求时)。
当连接到http1.1服务器时,持续连接将自动启用,或者当服务器发回一个keep-alive头时。当服务器明确的发回一个Connection: close头时,持续连接将被关闭。另外,ASIHTTPRequest对于包含body的请求(如post/put),将不会使用持续连接。你可以强制 这些请求使用持续连接,手动设置请求方法,然后将持续连接重新打开:
[request setRequestMethod:@"PUT"];
[request setShouldAttemptPersistentConnection:YES];
许多服务器不在响应头中提供连接保持多久的信息,所以可能在请求完成后的任何时间关闭连接。如果服务器不发送任何此类信息,ASIHTTPRequest将在请求完成后60秒内保持连接。有赖于你的服务器配置,这个时间可能过长或过短。
如果这个超时过长,服务器将在下一个请求有机会用它前踢掉你,如果ASIHTTPRequest碰到关闭连接的错误,它将在一个新连接上重试这个请求。
如果这个超时过短,服务器可能很乐意保持这个连接更久,但是ASIHTTPRequest将不必要的重开一个新连接,这会招致效率上的惩罚。
// Set the amount of time to hang on to a persistent connection before it should expire to 2 minutes
[request setPersistentConnectionTimeoutSeconds:120];
// Disable persistent connections entirely
[request setShouldAttemptPersistentConnection:NO];
强制使用http 1.0
[request setUseHTTPVersionOne:YES];
禁用安全证书验证
你可能希望使用这个测试你有一个自签名的安全证书。我推荐从一个可信的证书机构购买证书,并且只为产品程序打开证书验证。
[request setValidatesSecureCertificate:NO];
34、调试选项
ASIHTTPRequest提供了一些有助于调试请求行为的标志。这些标志可以在ASITHHPRequestConfig.h中找到。
当你打开这些标志后,请求会把他们干的事打印到控制台。
DEBUG_REQUEST_STATUS
打印总体请求的生命周期信息 -- 开始,结束上传,结束下载 等等。
DEBUG_THROTTLING
打印(粗略的)有多少带宽被使用的信息,如果请求被限流,还包括这如何发生的信息。同DEBUG_REQUEST_STATUS联合使用,可能对调试超时有帮助,因为你可以看到在哪一点请求停止了收发数据。
DEBUG_PERSISTENT_CONNECTIONS
打印请求如何重用持续连接的信息,如果你看到输出下面的信息:
Request attempted to use connection #1, but it has been closed - will retry with a new connection
…这表示你设置到persistentConnectionTimeoutSeconds的值可能过高,参看“配置持续连接”小节获得更多信息。
DEBUG_HTTP_AUTHENTICATION
从v1.8.1后添加,这会打印出关于请求如何处理http验证(基本/摘要/ntml)的信息。
DEBUG_FORM_DATA_REQUEST
打印ASIFormDataRequest将发送的请求body的概要。仅在使用ASIFormDataRequest有用。