All-Seeing Interactive Logo

ASIHTTPRequest documentation

Last updated: 31st December 2008


Creating a request

Creating a synchronous request

The simplest way to use ASIHTTPRequest. Sending the start message will execute the request in the same thread, and return control when it has completed (successfully or otherwise).

Check for problems by inspecting the error property.

To get the response as a string, call the dataString method. Don't use this for binary data - use recievedData to get an NSData object, or, for larger files, set your request to download to a file with the downloadDestinationPath property.

- (IBAction)grabURL:(id)sender
{
  NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
  ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
  [request start];
  NSError *error = [request error];
  if (!error) {
  	  NSString *response = [request dataString];
  }
}

Creating an asynchronous request

Does the same thing as the previous example, but in a background thread using NSOperationQueue. Using this method, you can queue up multiple requests at once, and NSOperationQueue will balance them across as many concurrent threads as it feels appropriate.

If you want to display some indication of progress for the queue, use the ASINetworkQueue subclass of NSOperationQueue instead. See below for more details.

We're setting custom selectors that will be called when the request succeeds or fails. If you don't set these, the defaults (requestFinished: and requestFailed:) will be used.

If you need to handle success and failure on many different types of request, you might do better to create a minimal subclass of ASIHTTPRequest for each, and override requestFinished: and failWithProblem:

- (IBAction)grabURLInTheBackground:(id)sender
{
   NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
   NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
   ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
   [request setDelegate:self];
   [request setDidFinishSelector:@selector(requestDone:)];
   [request setDidFailSelector:@selector(requestWentWrong:)];
   [queue addOperation:request];
}
 
- (void)requestDone:(ASIHTTPRequest *)request
{
   NSString *response = [request dataString];
}
 
- (void)requestWentWrong:(ASIHTTPRequest *)request
{
   NSError *error = [request error];
}

Sending data

Set request headers

You might use the request headers to spoof a user agent, as some sites may not let you in unless you're on their list of approved browsers.

ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request addRequestHeader:@"User-Agent" value:@"My-User-Agent-1.0"];

Add post data

To send post data, use the ASIFormDataRequest subclass. Data is posted as 'multipart/form-data' for compatibility with file uploads. Files are read as needed from disk, so including large files is OK, as long as your web server is setup to handle them.

ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"Ben" forKey:@"first_name"];
[request setPostValue:@"Copsey" forKey:@"last_name"];
[request setFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photo"];

Alternatively, you can populate the POST data yourself. create an NSData object with the data you want to send:

ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setPostBody:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]];

Downloading data

Saving response into a file

This is supported in Mac OS X applications only.

ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"]];

Reading the HTTP status code

ASIHTTPRequest doesn't do anything special with HTTP status codes, so it's up to you to look out for problems (eg: 404) and make sure you act appropriately.

ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request start];
int statusCode = [request responseStatusCode];

Reading response headers

ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request start];
NSString *poweredBy = [[request responseHeaders] objectForKey:@"X-Powered-By"];
NSString *contentType = [[request responseHeaders] objectForKey:@"Content-Type"];

Tracking progress

ASIHTTPRequest has two mechanisms for displaying upload and download progress:

  • If you are performing a single request, you set an upload and/or download progress delegate on that request
  • If you are performing multiple requests in a queue, use a ASINetworkQueue and set the progress delegate of the queue

Progress delegates can be NSProgressIndicators (Mac OS X) or UIProgressViews (iPhone). ASIHTTPRequest will automatically cater for the differences in the behaviour of these two classes.

IMPORTANT: If you are uploading to a site that requires authentication, the upload progress will be reset to its previous value every time it fails to supply valid authentication. For this reason, it is recommended that you only ever use an upload progress delegate when useSessionPersistance is YES (see below) when communicating with authenticating web servers, and ensure that you authenticate in another request before attempting to track the upload of a large amount of data.

Tracking download progress for a single request

In this example, myProgressIndicator is an NSProgressIndicator.

[myProgressIndicator setDoubleValue:0];
[myProgressIndicator setMaxValue:0];
NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDownloadProgressDelegate:myProgressIndicator];
[request start];
NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);

Tracking download progress for a set of requests

In this example, myProgressIndicator is an UIProgressView, myQueue is an ASINetworkQueue.

- (void)fetchThisURLFiveTimes:(NSURL *)url
{
   [myProgressIndicator setProgress:0];
   NSLog(@"Value: %f", [myProgressIndicator progress]);
   [myQueue cancelAllOperations];
   [myQueue setDownloadProgressDelegate:myProgressIndicator];
   [myQueue setDelegate:self];
   [myQueue setRequestDidFinishSelector:@selector(queueComplete:)];
   int i;
   for (i=0; i<5; i++) {
      ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url autorelease];
      [myQueue addOperation:request];
   }
   [myQueue go];
}
 
- (void)queueComplete:(ASINetworkQueue *)queue
{
   NSLog(@"Value: %f", [myProgressIndicator progress]);
}

Tracking upload progress for a single request

In this example, myProgressIndicator is an UIProgressView.

[myProgressIndicator setProgress:0];
NSLog(@"Value: %f",[myProgressIndicator progress]);
ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"Ben" forKey:@"first_name"];
[request setPostValue:@"Copsey" forKey:@"last_name"];
[request setUploadProgressDelegate:myProgressIndicator];
[request start];
NSLog(@"Value: %f",[myProgressIndicator progress]);

Tracking upload progress for a set of requests

In this example, myProgressIndicator is an NSProgressIndicator, myQueue is an ASINetworkQueue.

- (void)uploadSomethingFiveTimes:(NSURL *)url
{
   myProgressIndicator setDoubleValue:0];
   [myProgressIndicator setMaxValue:0];
   NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);
   [myQueue cancelAllOperations];
   [myQueue setUploadProgressDelegate:myProgressIndicator];
   [myQueue setDelegate:self];
   [myQueue setRequestDidFinishSelector:@selector(queueComplete:)];
   int i;
   for (i=0; i<5; i++) {
      ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url autorelease];
      [request setPostBody:[@"Some data" dataUsingEncoding:NSUTF8StringEncoding]];
      [myQueue addOperation:request];
   }
   [myQueue go];
}
 
- (void)queueComplete:(ASINetworkQueue *)queue
{
   NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]);
}

Handling authentication

Specify a username and password to use in the URL

NSURL *url = [NSURL URLWithString:@"http://username:password@allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];

Set a username and password to use for the request:

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUsername:@"username"];
[request setPassword:@"password"];

Use the keychain

If you turn on keychainPersistence, any valid username and password supplied will be stored in the keychain. Subsequent requests will reuse the username and password from the keychain, even if you quit and relaunch the application.

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUseKeychainPersistance:YES];
[request setUsername:@"username"];
[request setPassword:@"password"];

If you want to use the keychain but would rather manage it yourself, you might find the class methods relating to the keychain in ASIHTTPRequest.h helpful.

Using session authentication

The process for an HTTP request that requires authentication is:

  1. The request is sent
  2. The response headers say that authentication is required
  3. ASIHTTPRequest looks to see if we've provided a username and password using one of the methods described above
  4. If so, these are applied the the request and the request is resubmitted. If not, the delegate will be asked to supply a username and password. When they do so, the request is resubmitted.
  5. If the supplied username and password were incorrect, we got back to step 3.

This means that even if you supply a valid username and password before the request is submitted for the first time, the request will be submitted twice, once without the username and password, and again with it.

If useSessionPersistence is turned on (it is by default), the second request will re-use the authentication information from the first if it is valid for URL, and thus submit the request only once. If it is not valid, it's back to step 3 in the list above.

NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setUsername:@"username"];
[request setPassword:@"password"];
[request setUseSessionPersistance:YES]; //Shouldn't be needed as this is the default
 
//Should reuse our username and password
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];

Cookies

Persistent cookies

ASIHTTPRequest allows you to use the global store shared by all Mac OS X applications that use the CFNetwork or NSURLRequest APIs. If useCookiePersistance is on (it is by default), cookies will be stored in the shared NSHTTPCookieStorage container, and reused on other requests automatically. It's worth noting that ASIHTTPRequest might present cookies created in other applications if they are valid for a particular request.

You can clear all cookies created during a session like so:

[ASIHTTPRequest setSessionCookies:nil];

In this case, 'session cookies' refers to ALL cookies created during a session, rather cookies with no expiry date (often referred to as session cookies) that are removed when the application quits.

Alternatively, the convenience class method clearSession will clear all cookies created during the session, along with any cached authentication data.

Handle cookies yourself

If you prefer, you can turn off useCookiePersistance, and manage the set of cookies for a particular request manually:

//Create a cookie
NSDictionary *properties = [[[NSMutableDictionary alloc] init] autorelease];
[properties setValue:@"Test Value" 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 alloc] initWithURL:url] autorelease];
[request setUseCookiePersistance:NO];
[request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request start];
 
//Should be: I have 'Test Value' as the value of 'ASIHTTPRequestTestCookie'
NSLog(@"%@",[request dataString]);