ASIHTTPRequest类库简介和使用说明 加 一些实例

来源:互联网 发布:2016刷枪软件 编辑:程序博客网 时间:2024/06/01 08:43

官方网站: http://allseeing-i.com/ASIHTTPRequest/ 。可以从上面下载到最新源码,以及获取到相关的资料。

使用iOS SDK中的HTTP网络请求API,相当的复杂,调用很繁琐,ASIHTTPRequest就是一个对CFNetwork API进行了封装,并且使用起来非常简单的一套API,用Objective-C编写,可以很好的应用在Mac OS X系统和iOS平台的应用程序中。ASIHTTPRequest适用于基本的HTTP请求,和基于REST的服务之间的交互。

ASIHTTPRequest功能很强大,主要特色如下:

  • l 通过简单的接口,即可完成向服务端提交数据和从服务端获取数据的工作
  • l 下载的数据,可存储到内存中或直接存储到磁盘中
  • l 能上传本地文件到服务端
  • l 可以方便的访问和操作请求和返回的Http头信息
  • l 可以获取到上传或下载的进度信息,为应用程序提供更好的体验
  • l 支持上传或下载队列,并且可获取队列的进度信息
  • l 支持基本、摘要和NTLM身份认证,在同一会话中授权凭证会自动维持,并且可以存储在Keychain(Mac和iOS操作系统的密码管理系统)中
  • l 支持Cookie
  • l 当应用(iOS 4+)在后台运行时,请求可以继续运行
  • l 支持GZIP压缩数据
  • l 内置的ASIDownloadCache类,可以缓存请求返回的数据,这样即使没有网络也可以返回已经缓存的数据结果
  • l ASIWebPageRequest –可以下载完整的网页,包括包含的网页、样式表、脚本等资源文件,并显示在UIWebView /WebView中。任意大小的页面都可以无限期缓存,这样即使没有网络也可以离线浏览
  • l 支持客户端证书
  • l 支持通过代理发起Http请求
  • l 支持带宽限制。在iOS平台,可以根据当前网络情况来自动决定是否限制带宽,例如当使用WWAN(GPRS/Edge/3G)网络时限制,而当使用WIFI时不做任何限制
  • l 支持断点续传
  • l 支持同步和异步请求
2.1.1安装说明

如果想在iOS项目中使用ASIHTTPRequest,需要在项目中进行简单的配置,步骤如下:

1) 添加文件

往一个Xcode项目中添加第三方类库文件,有两种方式:

1. 第一种方式,在Finder中打开需要添加到文件或文件夹,在Xcode中打开要添加文件的项目,然后选中要添加的文件或文件夹,将它从Finder中拖到Xcode中,然后释放。在弹出的对话框中,如果文件已经拷贝到了项目文件目录中,则不需要选中“Copy items”的复选框;如果文件没有拷贝到项目文件目录,就需要选中“Copy items”的复选框,这样Xcode会自动把文件复制到项目文件目录下。如下图所示:
clip_image002
clip_image004

2. 第二种方式,在Xcode中,在要添加文件的分组下点右键,选中“Add Files to “My Project”…”菜单,在弹出的文件浏览对话框中选中要添加到文件或文件夹。如果要添加文件已经拷贝到了项目文件目录中,则不需要选中“Copy items”的复选框;如果文件没有拷贝到项目文件目录,就需要选中“Copy items”的复选框,这样Xcode会自动把文件复制到项目文件目录下。如下图所示:
clip_image006
clip_image008

根据上面的说明,添加ASIHTTPRequest相关文件到Xcode项目中,所需文件列表如下:

ASIHTTPRequestConfig.h

ASIHTTPRequestDelegate.h

ASIProgressDelegate.h

ASICacheDelegate.h

ASIHTTPRequest.h

ASIHTTPRequest.m

ASIDataCompressor.h

ASIDataCompressor.m

ASIDataDecompressor.h

ASIDataDecompressor.m

ASIFormDataRequest.h

ASIInputStream.h

ASIInputStream.m

ASIFormDataRequest.m

ASINetworkQueue.h

ASINetworkQueue.m

ASIDownloadCache.h

ASIDownloadCache.m

ASIAuthenticationDialog.h

ASIAuthenticationDialog.m

Reachability.h (在源码的 External/Reachability 目录下)

Reachability.m (在源码的 External/Reachability 目录下)

2) 链接相关类库

1. 选中项目

2. 选中目标

3. 跳转到“Build Phases”标签

4. 展开“Link Binary With Libraries”分组

5. 点击“+”添加类库

如下图所示:

clip_image010

6. 从列表中选择CFNetwork.framework,然后点击“Add”按钮。

clip_image012

7. 按照上一步相同的方法添加:SystemConfiguration.framework, MobileCoreServices.framework,CoreGraphics.framework和libz.1.2.3.dylib这几个类库。

8. 添加完后,可以将添加好的一起类库拖到Xcode项目的Frameworks目录下
clip_image014

2.1.2使用说明

ASIHTTPRequest有很多功能,所有功能说明都可以在其官方网站的相关文档中查到,限于篇幅,本章仅简单介绍一下如何使用ASIHTTPRequest来进行同步Http请求和异步Http请求。在后面的章节中,我们还会用到它的一些其他功能。

在使用ASIHTTPRequest之前,请确认已经正确安装,然后在需要应用它的代码文件头部,加入:

#import “ASIHTTPRequest.h”

这样就可以在代码中使用ASIHTTPRequest相关的类。

创建一个同步请求

这是ASIHTTPRequest最简单的一种使用模式,发送startSynchronous消息后即开始在同一线程中执行HTTP请求,线程将一直等待直到请求结束(请求成功或者失败)。通过检查error属性可以判断请求是否成功或者有错误发生。

要获取返回的文本信息,调用responseString方法。如果下载的是二进制文件,例如图片、MP3,则调用responseData方法,可以得到一个NSData对象。

- (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同步请求,应用程序的界面会锁定,无法进行任何操作,直到请求完成。

创建一个异步请求

上例中的同步请求,如果换成异步方式来调用,请求是在后台线程中运行,当请求执行完后再通知调用的线程。这样不会导致主线程进行网络请求时,界面被锁定等情况。

- (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

{

// 当以文本形式读取返回内容时用这个方法

NSString *responseString = [request responseString];

// 当以二进制形式读取返回内容时用这个方法

NSData *responseData = [request responseData];

}

- (void)requestFailed:(ASIHTTPRequest *)request

{

NSError *error = [request error];

}



下面为一些使用方法



//CFNetwork.framework,SystemConfiguration.framework, MobileCoreServices.framework, CoreGraphics.framework and libz.1.2.3.dylib

1.创建和运行请求
    1.1创建同步请求
{
  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];
    //responseData,downloadDestinationPath
  }
}
    1.2创建异步请求
{
   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];
}

    1.3.使用队列
{
    // Stop anything already in the queue before removing it
    [[self networkQueue] cancelAllOperations];

    // Creating a new queue each time we use it means we don't have to worry about clearing delegates or resetting progress tracking
    ASINetworkQueue *networkQueue=[ASINetworkQueue queue];
    [self setNetworkQueue:networkQueue];
    [[self networkQueue] setDelegate:self];
    [[self networkQueue] setRequestDidStartSelector:@selector(start:)];
    [[self networkQueue] setRequestDidReceiveResponseHeadersSelector:@selector(receiveResponseHeaders:)];
    [[self networkQueue] setRequestDidFinishSelector:@selector(requestFinished:)];
    [[self networkQueue] setRequestDidFailSelector:@selector(requestFailed:)];
    [[self networkQueue] setQueueDidFinishSelector:@selector(queueFinished:)];
    for (i=0; i<5; i++) {
        ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
        [[self networkQueue] addOperation:request];
    }

    [[self networkQueue] go];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    // You could release the queue here if you wanted
    if ([[self networkQueue] requestsCount] == 0) {

        // Since this is a retained property, setting it to nil will release it
        // This is the safest way to handle releasing things - most of the time you only ever need to release in your accessors
        // And if you an Objective-C 2.0 property for the queue (as in this example) the accessor is generated automatically for you
        [self setNetworkQueue:nil];
    }

    //... Handle success
    NSLog(@"Request finished");
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
    // You could release the queue here if you wanted
    if ([[self networkQueue] requestsCount] == 0) {
        [self setNetworkQueue:nil];
    }

    //... Handle failure
    NSLog(@"Request failed");
}

- (void)queueFinished:(ASINetworkQueue *)queue
{
    // You could release the queue here if you wanted
    if ([[self networkQueue] requestsCount] == 0) {
        [self setNetworkQueue:nil];
    }
    NSLog(@"Queue finished");
}
    1.4 取消异步请求
// Cancels an asynchronous request
[request cancel]
// Cancels an asynchronous request, clearing all delegates and blocks first
[request clearDelegatesAndCancel];

// 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];

2 发送数据
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request addRequestHeader:@"Referer" value:@"http://allseeing-i.com/"];
[request appendPostData:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]];
// Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody:
[request setRequestMethod:@"PUT"];
    2.1 POST表单
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"];
[request setData:imageData withFileName:@"myphoto.jpg" andContentType:@"image/jpeg" forKey:@"photo"];

3 下载数据
    3.1 保存到文件
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"];
    3.2 一旦接收到数据时
request:didReceiveData
重载该函数后,不再自动保存到文件
    3.3 读取状态码
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
int statusCode = [request responseStatusCode];
NSString *statusMessage = [request responseStatusMessage];
    3.4 读取报头
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSString *poweredBy = [[request responseHeaders] objectForKey:@"X-Powered-By"];
NSString *contentType = [[request responseHeaders] objectForKey:@"Content-Type"];
    3.5 操作文件编码
查找报头的Content-Type,没找到则NSISOLatin1StringEncoding
    3.6 重定向
4 进度跟踪
    4.1 单请求进度
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadProgressDelegate:myProgressIndicator];
[request startSynchronous];
NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);
    4.2 多请求进度
{
   [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]);
}
    4.5 简单进度vs精确进度
showAccurateProgress== YES
    4.6 自定义进度
request:didReceiveBytes:/request:didSendBytes:
request:incrementDownloadSizeBy:/request:incrementUploadSizeBy:

5 HTTP认证
    5.1 url方式
NSURL *url = [NSURL URLWithString:@"http://username:password@allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    5.2 request方式
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUsername:@"username"];
[request setPassword:@"password"];
    5.3 keychain存储
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setUseKeychainPersistence:YES];
[request setUsername:@"username"];
[request setPassword:@"password"];
    5.4 session存储
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];

    5.5 NTLM认证
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"];
    5.6 使用委托
异步请求,重载authenticationNeededForRequest:
[request retryUsingSuppliedCredentials];/[request cancelAuthentication];    
    5.7 服务器询问
    [request setShouldPresentCredentialsBeforeChallenge:NO];
    
6 cookie
默认useCookiePersistence打开,存储到NSHTTPCookieStorage容器
    6.1 创建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];
 
    6.2 读取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]);
    6.3 清除cookie
[ASIHTTPRequest setSessionCookies:nil];

7 压缩数据
Using gzip to handle compressed response data

As of v0.9, ASIHTTPRequest will notify the server that it can accept data compressed using gzip. If you are upgrading ASIHTTPRequest in an existing project, see the setup instructions for details of how to link with zlib.

Many webservers can compress data before sending it to the client - this results in faster downloads and lower bandwidth use, at the cost of additional CPU time on the server (to compress the data) and on the client (to decompress the data). Generally speaking, only certain types of data will be compressed - many binary formats like JPEG, GIF, PNG, SWF and PDF already compress their data, so gzip compression is normally not used to send them to a client. Text files like web pages and XML documents are perfect candidates for gzip compression, since they often contain a large amount of repeated information.

How to setup apache to gzip data using mod_deflate
Apache 2.x and above comes with the mod_deflate extension that allows it to transparently compress certain types of data. To turn it on, you need to enable mod_deflate in your apache configuration file, and add the mod_deflate directives to your virtual host config, or to your .htaccess file. More information is available here.

Using gzip in ASIHTTPRequest
- (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
}
When allowCompressedResponse is true, ASIHTTPRequest will add a Accept-Encoding header to the request specifying we can accept gzipped response data. If the response headers contain a Content-Encoding header that specifies the data is compressed, calls to responseData or responseString will uncompress the data before returning it. You can get the original compressed data by calling rawResponseData.

On-the-fly inflating of gzipped responses

By default, ASIHTTPRequest will wait until a request finishes to inflate (uncompress) a gzipped response. By setting a request's shouldWaitToInflateCompressedResponses property to NO, you can tell ASIHTTPRequest to inflate the data as is comes in. In some circumstances, this may result in a small speed boost, as data can be processed while a request is waiting for more of the response.

This feature may be especially useful if you need to parse the response with a streaming parser (eg an XML or JSON parser). With this option enabled, you can feed inflated data directly to your parser as it comes in by implementing request:didReceiveData: in your delegate.

Note that when shouldWaitToInflateCompressedResponses is set to NO, the raw (compressed) data will be discarded. See the comments in ASIHTTPRequest.h for more info.

Using gzip to compress request bodies

New in v1.0.3 is gzip compression for request bodies. Using this feature, your applications can compress the content of POST / PUT operations by setting shouldCompressRequestBody to YES. shouldCompressRequestBody is NO by default.

Apache’s mod_deflate can automatically inflate (decompress) gzipped request bodies when configured with SetInputFilter DEFLATE (More info). This approach works for CGI content, but not when you are using an Apache module built as a RESOURCE filter (such as mod PHP). In these cases, you need to inflate the data yourself.


ASIHTTPRequest cannot check if a server can accept a gzipped request body or not. Use this feature only if you are certain that the server you are talking to will understand a gzipped body.
Avoid gzipping content that is in a format that already uses compression (eg JPEG/PNG/GIF/PDF/SWF), you may well find the gzipped version is larger than the original.
Resuming interrupted downloads
As of v0.94, ASIHTTPRequest can resume partial downloads.

- (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];
}
This only works for downloading data to a file, and you must set allowResumeForFileDownloads to YES for:

Any download you might want to resume in future (or ASIHTTPRequest will remove the temporary download file when it is cancelled or dealloced)
Any download you want to resume
Additionally, you must set a temporary download path yourself (setTemporaryFileDownloadPath), with the path of the partial data. New data will be appended to this file, and the file moved to downloadDestinationPath when the download completes successfully.

Resuming works by reading the size of the file at temporaryFileDownloadPath, and then requesting the rest of the file using a Range: bytes=x HTTP header.


ASIHTTPRequest does not check for the presence of a Accept-Ranges header (because of the overhead of an additional HEAD request), so only use this feature when you are certain the that server you are connecting to supports partial downloads for the resource you want to download.
Streaming request bodies directly from disk
As of v0.96, ASIHTTPRequest can use files on disk as the request body. This means that it is no longer necessary to hold the request body in memory, which should result in a drastic reduction in memory usage for large POST/PUT operations.

There are several ways you can use this feature:

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 automatically use this feature when you use setFile:forKey:. The request will create a temporary file that will contain the full post body. Files are written a bit at a time to the relevant part of the body. The request is created using CFReadStreamCreateForStreamedHTTPRequest, using a read stream on the file as the source.

Regular ASIHTTPRequests

If you know your request is going to be large, turn on streaming from disk on the request:

[request setShouldStreamPostDataFromDisk:YES];
In the example below, we add NSData objects to the post body one at a time. There are two methods for doing this - adding data from memory (appendPostData:), or appendPostDataFromFile: to add the contents of a file.

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];
In this example, we want to PUT a large file directly. We set setPostBodyFilePath ourselves, ASIHTTPRequest will use this file as the 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];

IMPORTANT: You should not use setPostBody in the same request as any of the methods described above - they are mutually exclusive. setPostBody should only be used if you want to build the request body yourself, and plan on keeping the request body in memory.
Using a download cache

The API for ASIDownloadCache and ASICacheDelegate has changed in v1.8, and you will need to update your code if you are updating from v1.7.
In particular, the options available for cache policies are different, and you can now combine multiple cache policies for a single request.

ASIHTTPRequest can automatically store downloaded data in a cache for use later. This can be helpful in many situations:

You want to have access to the data when there is no internet connection and you can't download it again
You want to download something only if it has changed since you last downloaded it
The content you are working with will never change, so you only want to download it once
In previous versions of ASIHTTPRequest, handling the above situations would have meant storing the data manually yourself. Using a download cache may eliminate the need for writing any local storage mechanism yourself in some situations.

ASIDownloadCache is a simple URL cache that can be used for caching the response of GET requests. To be eligible for response caching, requests must succeed (no error), and the server must have returned a 200 OK HTTP response code.

Turning on the response cache is easy:

[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
After you've done this, all requests will use the cache automatically. If you prefer, you can set individual requests to use the shared cache on a case by case basis:

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
You aren't restricted to a single cache - you can create as many caches as you like. When you create a cache yourself, you must set the storage path for the cache - this should be a folder you have write access to:

 
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]];
About cache policies

Cache policies are the main way you control when information is stored in the cache, and when cached data will be used in preference to downloading the data again.

The cache policy of individual requests can be controlled using a request's cachePolicy property. Cache policies are defined using a bitmask, so you can combine multiple options to create the policy you want:

// 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];
You can use the following options to define a request's cache policy:

ASIUseDefaultCachePolicy    The default cache policy. When you set a request to use this, it will use the cache's defaultCachePolicy. ASIDownloadCache's default cache policy is 'ASIAskServerIfModifiedWhenStaleCachePolicy'. You should not combine this with other options.
ASIDoNotReadFromCacheCachePolicy    Requests will not read from the cache when using this option.
ASIDoNotWriteToCacheCachePolicy    Requests will not save to the cache when using this option.
ASIAskServerIfModifiedWhenStaleCachePolicy    This is the default cache policy for ASIDownloadCaches. When using this, requests will first look to see if a cached response is available in the cache. If there is no cached data, the request will proceed as normal.
If there is and the cached data has not expired, the request will use the cached data without contacting the server. If the cached data has expired, the request will perform a conditional GET to see if an updated version is available. If the server says the cached data is current, cached data will be used, and new data will not be downloaded. In this case, the cache's expiry time will be updated to match the new expiry date from the server. If the server provided updated content, it will be downloaded, and the new data and expiry written to the cache.
ASIAskServerIfModifiedCachePolicy    This is the same as ASIAskServerIfModifiedWhenStaleCachePolicy, except that requests will always ask the server if updated data is available.
ASIOnlyLoadIfNotCachedCachePolicy    When using this option, cached data will always be used if it exists, even if it should have expired.
ASIDontLoadCachePolicy    When using this option, requests will succeed only if a response is already cached. If no response for a request is cached, the request will stop, and no error will be set on the request.
ASIFallbackToCacheIfLoadFailsCachePolicy    When using this option, requests will fallback to cached data if the request fails. If cached data is used after a failure, the request will succeed without error. You would normally use this option in combination with others, as it is only useful for specifying the behaviour to use when something goes wrong.
When you set the defaultCachePolicy property of a cache, all requests that use that cache will use that cache policy unless they have a custom cache policy set on themselves.

About storage polices

Storage policies allow you to define how long a cache will store a particular response. ASIHTTPRequest currently supports two storage policies:

ASICacheForSessionDurationCacheStoragePolicy is the default. Responses will be stored only for the duration of the session, and will be removed the first time the cache is used, or when [ASIHTTPRequest clearSession] is called.

With ASICachePermanentlyCacheStoragePolicy, cached responses are stored permanently. To use this storage policy, set it on a request:

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
To manually clear the cache, call clearCachedResponsesForStoragePolicy:, passing the storage policy for the cached data you want to remove:

[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
Other cache-related features

// When you turn shouldRespectCacheControlHeaders off, the cache will store responses even if the server
// has explictly asked for them not be be cached (eg with a cache-control or pragma: no-cache header)
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
 
// Set secondsToCache on the request to override any expiry date for the content set by the server, and store
// this response in the cache until secondsToCache seconds have elapsed
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setSecondsToCache:60*60*24*30]; // Cache for 30 days
 
// After a request has run, didUseCachedResponse will return YES if the response was returned from the cache
[request didUseCachedResponse];
 
// Ask the cache for a path to store the response. This is the most efficient way to use a download cache,
// since data doesn't have to be copied into the cache when the request completes.
[request setDownloadDestinationPath:
   [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request]];
 
Writing your own cache

If you already have a download cache and would like to plug it in to ASIHTTPRequest, or you prefer to write your own, have your cache implement the ASICacheDelegate protocol.

Throttling bandwidth
As of v1.0.7, ASIHTTPRequest can throttle the bandwidth used by all requests to prevent it going over a user-defined limit. This may help iPhone applications that send or receive large amounts of data to make it through the app store review process.

Throttling works by using a global limit (in bytes) for how much data can be received or transmitted in one second. All requests share this limit. As they send or receive data, ASIHTTPRequest keeps track of how much data has been sent or received in the last second. If one request exceeds the limit, any others running will also have to wait for the remainder of the current measurement period.

On iOS, you can tell ASIHTTPRequest to automatically turn throttling on when using a WWAN (GPRS/Edge/3G) connection, and it will automatically turn it off when switching to WiFi.

// 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];
 
// 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];
 
// 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];
 
// Log how many bytes have been received or sent per second (average from the last 5 seconds)
NSLog(@"%qi",[ASIHTTPRequest averageBandwidthUsedPerSecond]);
 

IMPORTANT: Read this before enabling bandwidth throttling:
Bandwidth throttling should be considered an experimental feature: Use at your own risk.
Do not set the bandwidth limit too low - it’s probably best not to set it below ASIWWANBandwidthThrottleAmount
The actual bandwidth used by your application will always be slightly more than the limit you have set, because the measured bandwidth does not include the bandwidth used by HTTP headers.
The value of ASIWWANBandwidthThrottleAmount is not official, as far as I know, no bandwidth limit has been officially published.
You should not turn on bandwidth throttling unless your application is likely to send or receive large amounts of data. It may be best to turn it only only while performing requests that download or upload a large amount of data, and leave it off at all other times.
It probably goes without saying, but I make no guarantee your app won't be rejected for using excessive bandwidth when you turn on throttling.
Client certificates support
If your server requires the use of client certificates, as of v1.8 it is now possible to send them with your request.

// 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]];
There is a helper function in 'ClientCertificateTests.m' in the iPhone / iPad sample app that can create a SecIdentityRef from PKCS12 data (this function only works on iOS).

Working with Proxies
ASIHTTPRequest can detect system proxy settings and automatically apply them to requests. As of v1.0.6, it also supports PAC file proxy configuration, and authenticating proxies.

By default, ASIHTTPRequest will attempt to detect proxy settings automatically. However, should you wish, you can manually set proxy settings:

// 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"]];
Authenticating proxies

On Mac OS, ASIHTTPRequest can auto-detect credentials used for authenticating proxies if they are specified in System Preferences. On iOS, ASIHTTPRequest cannot auto-detect the credentials used for authenticating proxies, so you either have to set them manually, use delegation to ask your controller / the user for appropriate credentials, or let ASIAuthenticationDialog ask the user for them. Once valid proxy credentials have been obtained, they are stored in the keychain (when useKeychainPersistence is on) and are automatically reused.

Manually specifying credentials for the proxy

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"];
Using delegation to ask for proxy credentials

This works in the same way as using delegates to provide credentials for regular authentication, except that your delegate must respond to proxyAuthenticationNeededForRequest: (formerly proxyAuthorizationNeededForRequest:).


Using the built-in authentication dialog (currently iOS only)

New in v1.0.8 is the ASIAuthenticationDialog class. This can be used to ask the user for credentials for authenticating webservers and proxies.

If your delegate does not respond to proxyAuthenticationNeededForRequest:, by default, ASIHTTPRequest will show a dialog prompting the user to supply credentials. It appears by default for proxy servers so that all apps using ASIHTTPRequest can work with authenticating proxies without any additional effort on the part of the developer.

The proxy authentication dialog will not appear for synchronous requests running on the main thread.

If you prefer not to use the proxy authentication dialog, either implement proxyAuthenticationNeededForRequest: in your proxy, or set shouldPresentProxyAuthenticationDialog to false (in which case your application will not be able to connect to authenticating proxies). If you want to change the look and feel, subclass ASIHTTPRequest, and override showProxyAuthenticationDialog to show your custom dialog or ASIAuthenticationDialog subclass.

Miscellaneous features
Customising the user agent

To set the user agent your app will use, do this:

[ASIHTTPRequest setDefaultUserAgentString:@"MyApp 1.0"]
If you do not set a user agent, ASIHTTPRequest will create one for you. An example (for a Mac OS application):

My Application 1.0 (Macintosh; Mac OS X 10.5.7; en_GB)

You can also set the user agent on a per-request basis:

[request setUserAgent:@"MyApp 1.0"]
Continuing a request when your app enters the background on iOS

// iOS 4+ only
[request setShouldContinueWhenAppEntersBackground:YES];
Monitoring network activity

// 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
}
Disabling automatic updates to the network activity indicator (iOS only)

By default, ASIHTTPRequests will show the network activity indicator (in the status bar) on iOS devices when requests are using the network. If you prefer to manage this yourself, you can disable these updates:

[ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO];
Automatically retry requests when they time out

Make requests retry a maximum of 2 times if they encounter a timeout:

[request setNumberOfTimesToRetryOnTimeout:2];
Configuring persistent connections

By default, ASIHTTPRequest will attempt to keep connections to a server open so that they can be reused by other requests to the same server (this generally results in significant speed boost, especially if you have many small requests). Persistent connections will be used automatically when connecting to an HTTP 1.1 server, or when the server sends a keep-alive header. Persistent connections are not used if the server explicitly sends a 'Connection: close' header.

Many servers do not provide any information in response headers on how long to keep a connection open, and may close the connection at any time after a request is finished. If the server does not send any information about how long the connection should be used, ASIHTTPRequest will keep connections to a server open for 60 seconds after any request has finished using them. Depending on your server configuration, this may be too long, or too short.

If this timeout is too long, the server may close the connection before the next request gets a chance to use it. When ASIHTTPRequest encounters an error that appears to be a closed connection, it will retry the request on a new connection.

If this timeout is too short, and the server may be happy to keep the connection open for longer, but ASIHTTPRequest will needlessly open a new connection, which will incur a performance penalty.

// 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];
Forcing the use of HTTP 1.0

[request setUseHTTPVersionOne:YES];
Disabling secure certificate validation

You may wish to use this for testing purposes if you have a self-signed secure certificate. I recommend purchasing a certificate from a trusted certificate authority and leaving certificate validation turned on for production applications.

[request setValidatesSecureCertificate:NO];