connection:willSendRequest:redirectResponse example prject - iphone

Could anyone provide me with one please?
.h
#import "UntitledViewController.h"
#implementation UntitledViewController
- (id)init
{
self = [super init];
if (self)
{
NSURL *url = [NSURL URLWithString:#"http://tinyurl.com/a3cx"];
[self loadTinyURL:url];
}
return self;
}
- (void)loadTinyURL:(NSURL *)url
{
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if (!connection)
NSLog(#"could not connect with: %#", url);
else {
NSLog(#"this works");
}
}
- (NSURLRequest *)connection:(NSURLConnection *)connection
willSendRequest:(NSURLRequest *)request
redirectResponse:(NSURLResponse *)response
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
int statusCode = [httpResponse statusCode];
// http statuscodes between 300 & 400 is a redirect ...
if (response && statusCode >= 300 && statusCode < 400)
NSLog(#"redirecting to : %#", [request URL]);
return request;

you can use NSURLConnection samplecode based on either asynchronous or synchronous from apple website.you can know why we use this delegate method through the stackoverflow link

Related

Not getting server response string after successfully server response and successfully database insert

- (void)viewDidLoad
{
[super viewDidLoad];
NSString *jString = #"{\"block_face_line\" : [{\"longitude\" : -71.34345555,\"latitude\" : 42.7794343 },{\"longitude\" : -71.4473179666667,\"latitude\" : 42.7336227666667 }, {\"longitude\" : -71.4461721166667,\"latitude\" : 42.7321493333333 },{\"longitude\" : -71.4473179662267,\"latitude\" : 42.726227666667 } ],\"block_face_curb_side\" : \"LEFT\",\"block_face_collector_id\" : \"3\"}";
NSLog(#"JSON : : : : %#",jString);
NSURL *passurl = [NSURL URLWithString:[[NSString stringWithFormat:#"https://XXXX:XXXX#parkme.goldenware.com/cgi-bin/db.test?COMMAND=add&TABLE=block_faces&USER=1&SUBSYSTEM=json"] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog(#"passurl:%#",passurl);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:
[NSURL URLWithString:[passurl absoluteString]]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0];
NSLog(#"request:%#",request);
mFinalData = [jString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [jString length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:mFinalData];
receivedData = [[NSMutableData alloc] init];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
[connection start];
NSLog(#"Connection = %#", connection);
if(connection)
{
self.receivedData = [[NSMutableData data] initWithCapacity:2048];
NSLog(#"receive data:%#",self.receivedData);
NSString *stringData= [[NSString alloc] initWithData:receivedData
encoding:NSUTF8StringEncoding];
NSLog (#"result%#", stringData);
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Connection Failed To Response");
self->operationFailed = YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// if (!operationBreaked)
// [self.receivedData appendData:data];
// else
// {
// [connection cancel];
// NSLog(#" STOP !!!! Receiving data was stoped");
// }
NSLog(#"DONE1111");
[receivedData appendData:data];
NSLog(#"didreceivedata:%#",receivedData);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"[DO::didReceiveData] %d operation", (int)self);
NSLog(#"[DO::didReceiveData] ddb: %.2f, wdb: %.2f, ratio: %.2f",
(float)bytesReceived,
(float)expectedBytes,
(float)bytesReceived / (float)expectedBytes);
if ([response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*) response;
NSLog(#"Received status code: %d %#", [(NSHTTPURLResponse *) httpResponse statusCode],
[NSHTTPURLResponse localizedStringForStatusCode:[(NSHTTPURLResponse *) httpResponse statusCode]]) ;
}
NSLog(#"soapMsg1: %d", [receivedData length]);
[receivedData setLength:0];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [receivedData length]);
NSString *theXML = [[NSString alloc] initWithBytes:[receivedData mutableBytes] length: [receivedData length] encoding:NSUTF8StringEncoding];
NSLog(#"theXML:%#",theXML);
connection = nil;
receivedData =nil;
operationFinished = YES;
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
//
// connection:didReceiveAuthenticationChallenge:
//
// Show the authentication challenge alert to the user (or gives up if the
// failure count is non-zero).
//
- (void)connection:(NSURLConnection *)aConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)aChallenge
{
[aChallenge.sender useCredential:[NSURLCredential credentialForTrust:aChallenge.protectionSpace.serverTrust] forAuthenticationChallenge:aChallenge];
NSLog(#"Challenge Protection Space = %#",aChallenge.protectionSpace.host);
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
Getting server response 200 but not getting response string, response from server should be like:
// Status Code : OK , Status Description : OK ID=77
Or only ID number, for Example: `123`
Where is receivedData defined? Is it an ivar? What does your logging look like in -connection:didReceiveData:? Does recievedData show data in the log there? If so, what's clearing it by the time you get to -connectionDidReceiveResponse:?
In all likelihood, either receivedData isn't defined properly so is always nil, or isn't being retained properly, so it's being dealloc'd before you get to -connectionDidReceiveResponse:

iphone: didReceiveAuthenticationChallenge and canAuthenticateAgainstProtectionSpace are not called for secure restful service

I am trying to get data from a secure restful service. I follow many other posts alongwith
How to use NSURLConnection to connect with SSL for an untrusted cert?
But in my case didReceiveAuthenticationChallenge and canAuthenticateAgainstProtectionSpace are not get called.
please help if you could solve the problem or provide me some good example to call secure restful service.
NSURL *url = [NSURL URLWithString:#"https://76.69.53.126:8443/jaxrs/tdgateway/getCountries"];
NSError * error = nil;
NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[ NSURLConnection sendSynchronousRequest: urlRequest returningResponse: nil error: &error ];
NSLog(#"This is %#",url);
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(#"This is canAuthenticateAgainstProtectionSpace");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(#"This is didReceiveAuthenticationChallenge");
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
It could be different than NSURLAuthenticationMethodServerTrust, so just try this to start:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return YES;
}
You should not cancel it immediately:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSLog(#"This is didReceiveAuthenticationChallenge");
[[challenge sender] cancelAuthenticationChallenge:challenge];
}
NSString *XAPIKEY = #"myapikey";
NSString *LOGINUSER = #"login username";
NSString *LOGINPASS = #"passwords";
// Setup NSURLConnection
- (void) postRequest:(NSString *) requestFun requestData:(NSDictionary *) sendDataDic{
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", #"http://api.domain.com/index.php/api/", requestFun]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
[request setValue:#"application/x-www-form-urlencoded; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:XAPIKEY forHTTPHeaderField:#"X-API-KEY"];
if(sendDataDic != nil){
NSString *stringData = [self urlEncodedString:sendDataDic];
[request setHTTPBody:[stringData dataUsingEncoding:NSUTF8StringEncoding]];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[stringData length]] forHTTPHeaderField:#"Content-Length"];
}
[request setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
- (void) getRequest:(NSString *) requestFun requestData:(NSDictionary *) sendDataDic{
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", #"http://api.domain.com/index.php/api/", requestFun]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
[request setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:XAPIKEY forHTTPHeaderField:#"X-API-KEY"];
if(sendDataDic != nil){
NSString *stringData = [self urlEncodedString:sendDataDic];
[request setHTTPBody:[stringData dataUsingEncoding:NSUTF8StringEncoding]];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[stringData length]] forHTTPHeaderField:#"Content-Length"];
}
[request setHTTPMethod:#"GET"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection start];
}
static NSString *toString(id object) {
return [NSString stringWithFormat: #"%#", object];
}
static NSString *urlEncode(id object) {
NSString *string = toString(object);
return [string stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
}
-(NSString*) urlEncodedString:(NSDictionary*) ObjDic {
NSMutableArray *parts = [NSMutableArray array];
for (id key in ObjDic) {
id value = [ObjDic objectForKey: key];
NSString *part = [NSString stringWithFormat: #"%#=%#", urlEncode(key), urlEncode(value)];
[parts addObject: part];
}
return [parts componentsJoinedByString: #"&"];
}
// NSURLConnection Delegates
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
if ([challenge previousFailureCount] == 0) {
NSLog(#"received authentication challenge");
NSURLCredential *newCredential = [NSURLCredential credentialWithUser:LOGINUSER
password:LOGINPASS
persistence:NSURLCredentialPersistenceForSession];
NSLog(#"credential created");
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
NSLog(#"responded to authentication challenge");
} else {
NSLog(#"previous authentication failure");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSLog(#"response status code: %ld", (long)[httpResponse statusCode]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *strData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", strData);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"responded to authentication challenge");
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"responded to authentication challenge");
}

NSURLConnection delegate method

I am having a hard time to find any examples for NSURLConnection delegate method implementations.
I want to send data with a HTTP post with a button click. Not sure how to make a "submitting" screen and "submitted". (I know how to use spinner and will use them)
I am using this code under a botton click action, but unable to use any delegate stuff. Not sure how to implement them with my current set up.
NSMutableURLRequest *request =
[[NSMutableURLRequest alloc] initWithURL:
[NSURL URLWithString:#"http://myURL.com"]];
[request setHTTPMethod:#"POST"];
NSString *postString = [wait stringByAppendingString:co];
[request setValue:[NSString
stringWithFormat:#"%d", [postString length]]
forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:[postString
dataUsingEncoding:NSUTF8StringEncoding]];
//[[NSURLConnection alloc] initWithRequest:request delegate:self];
[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
[SVProgressHUD dismissWithSuccess:#"Submission Successful"];
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"Did Receive Response %#", response);
responseData = [[NSMutableData alloc]init];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
//NSLog(#"Did Receive Data %#", data);
[responseData appendData:data];
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
NSLog(#"Did Fail");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Did Finish");
// Do something with responseData
}
You need to use the new NSURLConnectionDataDelegate protocol.
I found some exemples here:
http://blog.kemalkocabiyik.com/index.php/2012/02/fetching-data-with-getpost-methods-by-using-nsurlconnection/
And if you can read portuguese: http://www.quaddro.com.br/blog/desenvolvimento-ios/baixando-conteudo-com-nsurlconnection-e-nsurlconnectiondatadelegate-no-ios
//Connection request
-(void)requestURL:(NSString *)strURL
{
// Create the request.
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:strURL]];
// Create url connection and fire request
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
//Delegate methods
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"Did Receive Response %#", response);
responseData = [[NSMutableData alloc]init];
}
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
{
//NSLog(#"Did Receive Data %#", data);
[responseData appendData:data];
}
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
NSLog(#"Did Fail");
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Did Finish");
// Do something with responseData
NSString *strData=[[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding];
NSLog(#"Responce:%#",strData);
}
http://codewithchris.com/tutorial-how-to-use-ios-nsurlconnection-by-example/
in this code you will use GCD ,Activity Indicator ,UIButton Action
on login button
First you will call StartActivityindicator on another thread and it keeps in moving until you remove or stop the Activityindicator.
then you will call the web service for login in GCD queue .
at the time you receive response from server call main queue to update the UI.
// After the interface declration
#interface LoginViewController ()
{
NSData *responseData;
dispatch_queue_t myqueue;
}
//Button Action
- (IBAction)Login_Button_Action:(id)sender
{
[NSThread detachNewThreadSelector: #selector(StartActivityindicator) toTarget:self withObject:nil];
myqueue =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_group_t group=dispatch_group_create();
dispatch_group_async(group, myqueue, ^{ [self loginWebService];});
}
-(void)loginWebService
{
//Combine Both url and parameters
NSString *UrlWithParameters = [NSString stringWithFormat:#"http://www.xxxxx.com?count=%#&user=%#&email=%#&password=%#",#"4",#"Username",s#"UserEmail",#"PAssword String"];
//Pass UrlWithParameters to NSURL
NSURL *ServiceURL =[NSURL URLWithString:UrlWithParameters];
NSMutableURLRequest *serviceRequest =[NSMutableURLRequest requestWithURL:ServiceURL];
[serviceRequest setHTTPMethod:#"POST"];
[serviceRequest setValue:#"application/json" forHTTPHeaderField:#"accept"];
[serviceRequest setValue:#"application/json" forHTTPHeaderField:#"content-type"];
//GEt Response Here
NSError *err;
NSURLResponse *response;
responseData = [NSURLConnection sendSynchronousRequest:serviceRequest returningResponse:&response error:&err];
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSInteger code = [httpResponse statusCode];
// check status code for response from server and do RND for code if you recive anything than 200
NSLog(#"~~~~~ Status code: %ld",(long)code);
if (code ==200)
{
// your response is here if you call right
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:responseData options: NSJSONReadingMutableContainers error: &err];
dispatch_async(dispatch_get_main_queue(),^{
// place the code here to update UI with your received response
[NSThread detachNewThreadSelector: #selector(StopActivityindicator) toTarget:self withObject:nil];
});
}
}
//Activity indicator Method to display
- (void) StartActivityindicator
{
mySpinner.hidden = NO;
[mySpinner startAnimating];
}
- (void) StopActivityindicator
{
mySpinner.hidden = YES;
[mySpinner stopAnimating];
}

How to use more than one delegate in iphone?

I am using below code to use json but i need more url connection in same page, how to achive it, thanks in advance
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog([NSString stringWithFormat:#"Connection failed: %#", [error description]]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
//do something with the json that comes back ... (the fun part)
}
- (void)viewDidLoad
{
[self searchForStuff:#"iPhone"];
}
-(void)searchForStuff:(NSString *)text
{
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.whatever.com/json"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
I am using php for web access
You could use instance variables to keep pointers to the connections. Then in the delegate callbacks, check for pointer equality to check which connection you're dealing with.
As NSValue conforms to NSCopying I use it to wrap the pointer to the connection, and use this as the key to access relevant data from a NSMutableDictionary. For example you might do something like the following:
-(void)searchForStuff:(NSString *)text withTarget:(id)target selector:(SEL)selector {
responseData = [[NSMutableData data] retain];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.whatever.com/json"]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:target,#"target",NSStringFromSelector(selector),#"selector",nil];
NSURLConnection *c = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[myMutableDictionary setObject:options forKey:[NSValue valueWithPointer:c]];
[c release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSValue *p = [NSValue valueWithPointer:connection];
NSDictionary *options = [myMutableDictionary objectForKey:p];
if (options) {
id target = [options objectForKey:#"target"];
SEL selector = NSSelectorFromString([options objectForKey:#"selector"]);
if (target && selector && [target respondsToSelector:selector]) {
[target performSelector:selector withObject:responseData];
}
}
}
Don't do any of that.
Instead use the brilliant ASIHTTPRequest library, which makes everything much simpler and better. Literally, since I discovered ASI a couple years ago, I haven't written a single NSURLConnection, not one.
ASI's block interface lets you configure a request object with its handler code before firing it, and does away with any need for delegation.
__block ASIHTTPRequest *r = [ASIHTTPRequest requestWithUrl:myNSURLObject];
[r setCompletionBlock:^{
NSLog([r responseString]); //for instance
}];
[r startAsynchronous];
If blocks scare you, you can also point a particular request at a particular method, so different request types can be handled separately:
- (void) viewDidLoad { //or wherever
ASIHTTPRequest *r = [ASIHTTPRequest requestWithUrl:myFirstURL];
r.delegate = self;
[r setDidFinishSelector:#selector(requestDone:)];
[r startAsynchronous];
}
// then later on...
- (void)requestDone:(ASIHTTPRequest *)request
{
NSString *response = [request responseString];
}
You don't actually need more than one delegate. You need more than one NSURLConnection and you can test to see which one is calling the delegate method.
For example. Assuming the following instance variable (or properties):
NSURLConnection *connectionA;
NSURLConnection *connectionB;
NSMutableData *dataA;
NSMutalbeData *dataB;
First you instantiate each NSURLConnection variable
-(void)searchA:(NSString *)text
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.a.com/%#", text]]];
connectionA = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void)searchB:(NSString *)text
{
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.b.com/%#", text]]];
connectionB = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
Then you can test to see which connection is calling the delegate method and customize the implementation based on the connection
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
if (connection == connectionA) {
[dataA appendData:data];
}
else if (connection == connectionB) {
[dataB appendData:data];
}
}
You'll need to do this for each delegate method.

Synchonous SSL certificate handling on iPhone

I was wondering if anyone can help me understand how to add SSL certificate handling to synchronous
connections to a https service.
I know how to do this with asynchronous connections but not synchronous.
NSString *URLpath = #"https://mydomain.com/";
NSURL *myURL = [[NSURL alloc] initWithString:URLpath];
NSMutableURLRequest *myURLRequest = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[myURL release];
[myURLRequest setHTTPMethod:#"POST"];
NSString *httpBodystr = #"setting1=1";
[myURLRequest setHTTPBody:[httpBodystr dataUsingEncoding:NSUTF8StringEncoding]];
NSHTTPURLResponse* myURLResponse;
NSError* myError;
NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest returningResponse:&myURLResponse error:&myError];
//I guess I am meant to put some SSL handling code here
Thank you.
Using the static sendSynchronousRequest function is not posible, but i found an alternative.
First of all NSURLConnectionDataDelegate object like this one
FailCertificateDelegate.h
#interface FailCertificateDelegate : NSObject <NSURLConnectionDataDelegate>
#property(atomic,retain)NSCondition *downloaded;
#property(nonatomic,retain)NSData *dataDownloaded;
-(NSData *)getData;
#end
FailCertificateDelegate.m
#import "FailCertificateDelegate.h"
#implementation FailCertificateDelegate
#synthesize dataDownloaded,downloaded;
-(id)init{
self = [super init];
if (self){
dataDownloaded=nil;
downloaded=[[NSCondition alloc] init];
}
return self;
}
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace: (NSURLProtectionSpace *)protectionSpace {
NSLog(#"canAuthenticateAgainstProtectionSpace:");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge {
NSLog(#"didReceiveAuthenticationChallenge:");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[downloaded signal];
[downloaded unlock];
self.hasFinnishLoading = YES;
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[dataDownloaded appendData:data];
[downloaded lock];
}
-(NSData *)getData{
if (!self.hasFinnishLoading){
[downloaded lock];
[downloaded wait];
[downloaded unlock];
}
return dataDownloaded;
}
#end
And for use it
FailCertificateDelegate *fcd=[[FailCertificateDelegate alloc] init];
NSURLConnection *c=[[NSURLConnection alloc] initWithRequest:request delegate:fcd startImmediately:NO];
[c setDelegateQueue:[[NSOperationQueue alloc] init]];
[c start];
NSData *d=[fcd getData];
Now you will have all benefits of have an async use of nsurlconnection and benefits of a simple sync connection, the thread will be blocked until you download all data on the delegate, but you could improve it adding some error control on FailCertificateDelegate class
EDIT: fix for big data. based on Nikolay DS comment. Thanks a lot
I had a similar issue. In my case i had an a-synchronous connection working with ssl as required using the two delegate methods that allowed me to accept any certificate:
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
But i was stuck on doing the same in a synchronous manner. I searched the web until i found your post and unfortunately another stackoverflow post where it is hinted that you cannot perform synch calls on NSURLConnection and work with ssl (because of the lack of a delegate to handle the ssl authentication process).
What i ended up doing is getting ASIHTTPRequest and using that. It was painless to do and took me about an hour to set up and its working perfectly. here is how i use it.
+ (NSString *) getSynchronously:(NSDictionary *)parameters {
NSURL *url = [NSURL URLWithString:#"https://localhost:8443/MyApp/";
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSString *parameterJSONString = [parameters JSONRepresentation];
[request appendPostString:parameterJSONString];
[request addRequestHeader:#"User-Agent" value:#"MyAgent"];
request.timeOutSeconds = CONNECTION_TIME_OUT_INTERVAL;
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
NSString *responseString = [request responseString];
if (request.error) {
NSLog(#"Server connection failed: %#", [request.error localizedDescription]);
} else {
NSLog(#"Server response: %#", responseString);
}
return responseString;
}
The important part of course is the
[request setValidatesSecureCertificate:NO];
Another alternative for you is to handle the download in another thread with an a-synch connection using the two methods above and block the thread from which you want the synch connection until the request is complete
Im close to finding the solution for this with the code below. This works but often crashes
probably because I am doing something wrong in the way I code this and I don't have a strong understanding of the methods used. But if anyone has any suggestions on how to improve this
than please post.
Just after the line:
NSError* myError;
and just before the line:
NSData* myDataResult = [NSURLConnection sendSynchronousRequest:myURLRequest
returningResponse:&myURLResponse error:&myError];
add:
int failureCount = 0;
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost:#"mydomain.com" port:443 protocol:#"https" realm:nil
authenticationMethod:NSURLAuthenticationMethodServerTrust];
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:myURL MIMEType:#"text/html"
expectedContentLength:-1 textEncodingName:nil];
NSURLAuthenticationChallenge *challange = [[NSURLAuthenticationChallenge alloc]
initWithProtectionSpace:protectionSpace proposedCredential:[NSURLCredential
credentialForTrust:protectionSpace.serverTrust] previousFailureCount:failureCount
failureResponse:response error:myError sender:nil];