Friday, June 25, 2010

Audio/Video url String To Data and Data To Audio/Video String conversion

NSString *videoURL=@"http://10.0.2.94:8080/test/v.m4v"; // for MP3 url :  http://10.0.2.94:8080/test/a.mp3
 
//NSURL *movieURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@",videoURL]];//3908777 bytes
NSString *stringData = [NSString stringWithString:videoURL];
NSData *theData = [[NSData alloc] initWithData:[stringData dataUsingEncoding:NSASCIIStringEncoding]];
NSString* theString = [[NSString alloc] initWithData:theData encoding:NSASCIIStringEncoding];
    
NSURL *url = [NSURL URLWithString:theString];
moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
moviePlayer.scalingMode = MPMovieScalingModeNone;
moviePlayer.movieControlMode = MPMovieControlModeDefault;
[moviePlayer play];

Regards,
Dinesh

Thursday, June 24, 2010

Make POST request, handle cookie iPhone

[[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways];

NSString *post =[NSString stringWithFormat:@"name=%@&pass=%@",@"foo", @"bar"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:@"http://www.mywebserver.com/login.php"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];

NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *data=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(data);

// HOW to Check if there was a Cookie dropped??


// Make another request..

Wednesday, June 23, 2010

How to get correct Set-Cookie headers for NSHTTPURLResponse?



I want to use the following code to login to a website which returns its cookie information in the following manner:
Set-Cookie: 19231234
Set-Cookie: u2am1342340
Set-Cookie: owwjera


I'm using the following code to log in to the site, but the print statement at the end doesn't output anything about "set-cookie". On Snow leopard, the library seems to automatically pick up the cookie for this site and later connections sent out is set with correct "cookie" headers. But on leopard, it doesn't work that way, so is that a trigger for this "remember the cookie for certain root url" behavior?

NSMutableURLRequest *request = [[[NSMutableURLRequest 
alloc] init] autorelease];
[request setURL:[NSURL URLWithString:uurl]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"keep-live" forHTTPHeaderField:@"Connection"];
[request setValue:@"300" forHTTPHeaderField:@"Keep-Alive"];
[request setHTTPShouldHandleCookies:YES];

[request setHTTPBody:postData];
[request setTimeoutInterval:10.0];

NSData *urlData;
NSHTTPURLResponse *response;
NSError *error;
urlData = [NSURLConnection sendSynchronousRequest:request
                                returningResponse:&response
                                            error:&error];

NSLog(@"response dictionary %@",[response allHeaderFields]);

Tuesday, June 22, 2010

ASIHTTPRequest documentation

http://allseeing-i.com/ASIHTTPRequest/How-to-use



Creating a request
Creating a synchronous request
The simplest way to use ASIHTTPRequest. Sending the startSynchronous 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 responseString method. Don't use this for binary data - use responseData 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 requestWithURL:url];
  [request startSynchronous];
  NSError *error = [request error];
  if (!error) {
    NSString *response = [request responseString];
  }
}
info.png
In general, you should use asynchronous requests in preference to synchronous requests. When you use ASIHTTPRequest synchronously from the main thread, your application's user interface will lock up and become unusable for the duration of the request.
Synchronous requests are only really suitable for software without a UI (like a script that runs from the terminal), or if you are running the request from a separate thread that you maintain (perhaps from inside your own NSOperation, for example).

Creating an asynchronous request
Does the same thing as the previous example, but the request runs in the background.
- (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];
}
Note that we set the delegate property of the request so we can receive notification when the request completes or fails.
This is the simplest way to create an asynchronous request, and it will run in the current thread. For more complex operations (such as tracking progress across multiple requests), you might want to create your own queue, which is what we’ll cover next.
Using a queue
This example does the same thing again, but we've created an NSOperationQueue for our request.
Using an NSOperationQueue (or ASINetworkQueue, see below) gives you more control over asynchronous requests. When using a queue, only a certain number of requests can run at the same time. If you add more requests than the queue's maxConcurrentOperationCount property, requests will wait for others to finish before they start.
- (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];
}

In the above sample, ‘queue’ is a retained NSOperationQueue property of our controller.
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, as in the previous example.

Handling success and failure for multiple requests
If you need to handle success and failure on many different types of request, you have several options:
  1. If your requests are all of the same broad type, but you want to distinguish between them, you can set the userInfo NSDictionary property of each request with your own custom data that you can read in your finished / failed delegate methods.
  2. If you need to handle success and failure in a completely different way for each request, set a different setDidFinishSelector / setDidFailSelector for each request
  3. For more complex situations, or where you want to parse the response in the background, create a minimal subclass of ASIHTTPRequest for each type of request, and override requestFinished: and failWithProblem:.
info.png
It’s best to avoid using the request’s URL to distinguish between different requests in your delegate methods, because the URL property can change when a request is redirected.

About ASINetworkQueues
ASINetworkQueue is a subclass of NSOperationQueue that provides some additional functionality.
Its primary purpose is to allow you to track the upload and/or download progress of a whole queue (Read more about progress tracking).
ASINetworkQueues can also automatically update the network activity indicator in the status bar in iPhone applications.
In addition, ASINetworkQueues provide some extra delegate method selectors:
  • requestDidFinishSelector
    Called each time a request in the queue completes successfully. You can use this as an alternative to specifying a didFinishSelector and setting a delegate on requests you add to the queue
  • requestDidFailSelector
    Called each time a request in the queue fails. You can use this as an alternative to specifying a didFailSelector and setting a delegate on requests you add to the queue
  • queueDidFinishSelector
    Called when the whole queue has completed, whether individual requests failed or succeeded.
To use these, set the delegate of the queue (rather than the delegate of the request) to the controller that implements the methods that these selectors represent.

ASINetworkQueues work slightly differently from NSOperationQueues, in that requests added to them will not start running immediately. When using an ASINetworkQueue, add all the operations you want to run, then call [queue go].
When a request in an ASINetworkQueue fails, the queue will by default cancel all other requests. You can disable this behaviour with [queue setShouldCancelAllRequestsOnFailure:NO].
ASINetworkQueues can only run ASIHTTPRequest operations, they cannot be used for generic operations. Attempting to add an NSOperation that is not an ASIHTTPRequest will generate an exception.

info.png
There is a complete example here that shows the basics of creating and using an ASINetworkQueue:
Cancelling an asynchronous request
To cancel an asynchronous request (either a request that was started with [request startAsynchronous] or a request running in a queue you created), call [request cancel]. Note that you cannot cancel a synchronous request.
When using an ASINetworkQueue, all other requests will be cancelled when you cancel an individual request unless the queue’s shouldCancelAllRequestsOnFailure is NO (YES is the default).
// Cancels an asynchronous request
[request cancel]

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

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 requestWithURL:url];
[request addRequestHeader:@"User-Agent" value:@"My-User-Agent-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)

Sending data with POST or PUT requests
To send POST data in a manner compatible with web page forms, use the included ASIFormDataRequest subclass. Data is posted in 'application/x-www-form-urlencoded' format, or 'multipart/form-data' format when uploading binary data or files. Data in files is read as needed from disk, so POSTing large files is OK, as long as your web server is setup to handle them.
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"];
Alternatively, you can populate the request body yourself. This is especially useful when you are connecting to a RESTful web service and want to PUT some data. Create an NSData object with the data you want to send:
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"];
If you want to send large amounts of data and aren't using an ASIFormDataRequest, see the information on streaming post bodies from disk below.
Downloading data
Downloading the response directly to a file
If the resource you are requesting is fairly large, you can save memory by downloading directly to a file. This way, ASIHTTPRequest won't have to keep the whole response in memory at once.
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"]];
When downloading data to a file using downloadDestinationPath, data will be saved in a temporary file while the request is in progress. This file's path is stored in temporaryFileDownloadPath. When the request completes successfully, one of two things happen:
  • If the data is gzip compressed (see information on gzip compression), the compressed file will be uncompressed into downloadDestinationPath, and the temporary file will be deleted
  • If the data is not compressed, the temporary file is moved to downloadDestinationPath, overwriting any previous file
info.png
Note that if the response body is empty, no file will be created. If there is a possibility that a request may return an empty body, make sure you check the file exists before you attempt to do anything with it.

Reading the HTTP status code
ASIHTTPRequest doesn't do anything special with most HTTP status codes (except redirection and authentication status codes, see below for more info), so it's up to you to look out for problems (eg: 404) and make sure you act appropriately.
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
int statusCode = [request responseStatusCode];
NSString *statusMessage = [request responseStatusMessage];
Reading response headers
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSString *poweredBy = [[request responseHeaders] objectForKey:@"X-Powered-By"];
NSString *contentType = [[request responseHeaders] objectForKey:@"Content-Type"];
Handling text encodings
ASIHTTPRequest will attempt to read the text encoding of the received data from the Content-Type header. If it finds a text encoding, it will set responseEncoding to the appropriate NSStringEncoding. If it does not find a text encoding in the header, it will use the value of defaultResponseEncoding (this defaults to NSISOLatin1StringEncoding).
When you call [request responseString], ASIHTTPRequest will attempt to create a string from the data it received, using responseEncoding as the source encoding.
Handling redirection
ASIHTTPRequest will automatically redirect to a new URL when it encounters one of the following HTTP status codes, assuming a Location header was sent:
  • 301 Moved Permanently
  • 302 Found
  • 303 See Other
When redirection occurs, the value of the response data (responseHeaders / responseCookies / responseData / responseString etc) will reflect the content received from the final location.
Cookies set on any of the urls encountered during a redirection cycle will be stored in the global cookie store, and will be represented to the server on the redirected request when appropriate.
You can turn off automatic redirection by setting the request’s shouldRedirect property to NO.
info.png
As of ASIHTTPRequest 1.5, automatic redirects always redirect using a GET request (with no body). This behaviour matches the way most browsers work, not the HTTP spec, which specifies that 301 and 302 redirects should use the original method.
Tracking progress
Each ASIHTTPRequest has two delegates that can be used for tracking progress - downloadProgressDelegate (for downloads) and uploadProgressDelegate (for uploads).
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. If you want, you can also use a custom class as a progress delegate, as long as it responds to setProgress:.
  • 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, and you want to track overall progress for all requests in the queue, use a ASINetworkQueue and set the progress delegate of the queue
  • If you want to do both of these at the same time, this is possible too (as of v0.97)
info.png
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 useSessionPersistence 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.

info.png
Tracking progress for uploads where the request body is less than 128KB is currently not possible. For requests larger than 128KB, progress delegates will not receive information on the progress of the first 128KB of post data. This is because of limitations in the CFNetwork API. I have filed a feature enhancement with Apple (bug id 6596016), hopefully they will modify CFNetwork in future to make this possible.
Update 21st June 2009: The wonderful folks at Apple were kind enough to address my bug report! In the iPhone 3.0 SDK, it looks like the buffer size has been reduced to 32KB, which makes accurate upload progress tracking a lot more reliable.

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 requestWithURL:url];
[request setDownloadProgressDelegate:myProgressIndicator];
[request startSynchronous];
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 requestWithURL:url];
      [myQueue addOperation:request];
   }
   [myQueue go];
}

- (void)queueComplete:(ASINetworkQueue *)queue
{
   NSLog(@"Value: %f", [myProgressIndicator progress]);
}
Notice that for ASINetworkQueues, we have to call [myQueue go] to start the queue.
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 requestWithURL:url];
[request setPostValue:@"Ben" forKey:@"first_name"];
[request setPostValue:@"Copsey" forKey:@"last_name"];
[request setUploadProgressDelegate:myProgressIndicator];
[request startSynchronous];
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 = [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]);
}
Accurate progress vs simple progress
ASIHTTPRequest provides two approaches for displaying progress, simple progress, and accurate progress. They are controlled using the showAccurateProgress of ASIHTTPRequests and ASINetworkQueues. When you set showAccurateProgress on a request, it affects only that request. When you set it on a queue, it affects all requests in the queue.
Simple progress
When using simple progress, progress will update only when a request completes. For a single request, this means you get two progress updates - 0% complete, and 100% complete. For a queue with four requests, you would get five progress updates, 0%, 25%, 50%, 75% and 100%, with each increment representing a request that has completed.
Simple progress (showAccurateProgress = NO) is the default for ASINetworkQueues, and is well suited to queues with a large number of small uploads / downloads.
Accurate progress
When using accurate progress, progress will be updated as bytes are sent or received. It is best for requests that send or receive a large amount of data, and will give a much better indication of how much data has been sent or received for requests that take some time.
Using accurate progress will slightly degrade the performance of uploads, since progress delegates (which are likely to be UIProgressViews or NSProgressIndicators) will be redrawn much more frequently.
Using accurate progress has a much greater effect on performance for downloads when using a queue, since the queue will first perform a HEAD request for each GET request it contains so it can determine the overall size of the data to be downloaded before downloading commences. Using accurate progress is highly recommended if you are downloading large files from a queue, but you should avoid it for queues that contain a large number of small downloads.
Accurate progress (showAccurateProgress = YES) is the default for ASIHTTPRequests that run synchronously.
Handling authentication
If you're connecting to a server that requires authentication, you might want to take a look at this flowchart that shows how ASIHTTPRequest finds and applies credentials to requests.
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 requestWithURL:url];
Set a username and password to use for the request:
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[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 requestWithURL:url];
[request setUseKeychainPersistence: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
If useSessionPersistence is turned on (it is by default), ASIHTTPRequest stores credentials in memory and can re-use them for subsequent requests.
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];
NTLM authentication
To authenticate with a Windows server that uses the NTLM scheme, you also need to specify the domain you are authenticating against.
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"];
Using delegation to provide credentials
Rather than specifying authentication credentials in advance, you might prefer to let each request ask its delegate for credentials if it can't find them in the session authentication cache or keychain. This might be helpful if you want to connect to a server where you aren't sure in advance what kind of authentication (if any) will be required.
Make sure your delegate implements authenticationNeededForRequest:, and ASIHTTPRequest will pause a request while it waits for the delegate to let it know what credentials to use. When you have the credentials you need, simply set them on the request, and call [request retryUsingSuppliedCredentials];. If you want to cancel, you must call [request cancelAuthentication]. This will cancel the request.
As of v1.0.8, request delegates will only receive one authenticationNeededForRequest: or proxyAuthenticationNeededForRequest: at once. Other requests requiring authentication will pause while the delegate handles the first request. If credentials are provided, any other requests currently in progress will attempt to reuse them, assuming they are valid for the url. If the delegate cancels authentication, and the queue's shouldCancelAllRequestsOnFailure is YES, all the other requests will cancel without attempting to ask for credentials.
info.png
You cannot use the delegation pattern for authentication when using synchronous requests running on the main thread.
In older versions this would have caused your app to hang, as of v1.0.8 the delegate methods will no longer be called.

auth-dialog.png
Using the built-in authentication dialog (currently iPhone OS only)
New in v1.0.8 is the ASIAuthenticationDialog class. This is primarily used for working with authenticating proxies (see below), but it can be used to ask the user for credentials for authenticating webservers.
For the best user experience, most apps that connect to a single service should implement authenticationNeededForRequest: in their request delegates, or avoid the use of delegation-style authentication altogether. However, there may be some occasions when the use of ASIHTTPRequest's standard authentication dialog for regular authentication may be advantageous:
  • You don't want to create your own login form
  • You may need to fetch data from an external source, and aren't certain if it will require authentication or not
For these cases, set shouldPresentAuthenticationDialog to true on your requests, and, if your delegate does not implement authenticationNeededForRequest:, users will see the dialog.
Only one dialog can appear at once, and other requests requiring authentication will pause while the dialog is visible. If credentials are provided, any other requests currently in progress will attempt to reuse them, assuming they are valid for the url. If the delegate cancels authentication, and the queue's shouldCancelAllRequestsOnFailure is YES (as per the default), all the other requests will cancel without attempting to ask for credentials.
The authentication dialog will not appear for synchronous requests running on the main thread.
The dialog is partly modelled on the authentication dialog that Safari uses on the iPhone, and includes:
  • A message to indicate these credentials are for a webserver (as opposed to a proxy)
  • The hostname or IP of the server you are connecting to
  • The authentication realm (if one was supplied)
  • Fields to enter a username and password
  • When connecting to a server that uses the NTLM scheme, the dialog also includes a field for the domain
  • A note about whether the credentials are sent in plain text or not (ie: They are sent in plain text only when using Basic authentication without SSL)
If you want to change the look and feel, subclass ASIHTTPRequest, and override showAuthenticationDialog to show your custom dialog or ASIAuthenticationDialog subclass.
Presenting credentials before the server asks for them
ASIHTTPRequest will by default present credentials to the server (if it has credentials to use) when it first makes a request, rather than waiting for the server to ask for credentials. This can result in better performance for applications using authentication, since it avoids an extra request. For Basic Authentication, credentials can be presented on the very first request. For other authentication schemes, credentials can be presented only after another request has successfully authenticated with the server.
You may wish to disable this feature if:
  • Your application may use multiple sets of credentials to talk to the same server at once
  • Security is paramount for your application. Using this feature is inherently less secure, since credentials are sent before you have a chance to validate that you are connecting to the server you thought you were connecting to.
To disable this feature, use this code:
[request setShouldPresentCredentialsBeforeChallenge:NO];
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 useCookiePersistence 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 useCookiePersistence, and manage the set of cookies for a particular request manually:
//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]);
Encoding and decoding cookie values
As of v0.994, ASIHTTPRequest no longer url-encodes / url-decodes the values of cookies automatically. (see the changelog for the reasons behind this change). The included ASINSStringAdditions category for NSString allows you to url-decode a cookie value to obtain a regular string, or encode a string to be used as a cookie value.
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.
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.

info.png
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.
Resume 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.

info.png
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];
info.png
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.
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 iPhone OS, 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 iPhone OS
[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 iPhone OS
[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]);

info.png
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.
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 iPhone OS, 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:).
proxy-auth-dialog.png
Using the built-in authentication dialog (currently iPhone OS 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.