What is the best starting point to learn connecting to ssl web services by iphone?
Until now i did some basic connections over http via SOAP etc. but i have no experience on https. Any good sources, tutorials, starting references, "use nsurl...class"s are appreciated
NSURLConnection works by default with SSL and can access https sites. Issues may appear regarding letting user trust SSL certificates, here's a discussion on this that I've found to be interesting.
i'm posting a sample https client. it ignores if server certificate is not valid.
the server has a webget method with uritemplate=username({usercode})/password({passcode})
you can use CharlesProxy to check your outgoing message
#import "Hello_SOAPViewController.h"
#interface NSURLRequest (withHttpsCertificates)
+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host;
+ (void)setAllowsAnyHTTPSCertificate:(BOOL)allow forHost:(NSString*)host;
#end
#implementation Hello_SOAPViewController
NSMutableData *webData;
- (void)viewDidLoad {
//////////////////////////////////////////////////
//Web Service Call
//////////////////////////////////////////////////
NSURL *url = [NSURL URLWithString:#"https://192.168.1.105/HelloService/Service.svc/username(user)/password(xxx)"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
[theRequest addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPMethod:#"GET"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if(theConnection) {
webData = [[NSMutableData data] retain];
}
else {
NSLog(#"theConnection is NULL");
}
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConnection:%#",[error description]);
if ([error code] == -1001 ){//isEqualToString:#"timed out"]) {
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:#"Connection Error" message:#"Server Unresponsive" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[alertView show];
}else{
UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:#"Connection Error" message:#"Check your internet connection " delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil] autorelease];
[alertView show];
}
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
///////////////////////
//Process Your Data here:
///////////////////////
[connection release];
[webData release];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
Check out ASIHTTPRequest. It is very stable, non-leaky, easy-to-use and includes a bunch of goodies like download file resuming, progress bar support etc… It also has authentication support
Related
I have an application and I used to get my json data with dataWithContentsOfURL.
But because I need to get it an asynchrone fashion.
Now that I use NSURLConnection to handle this I don't receive any useful data all I get is statuscode 200 in the didReceiveResponse method but didReceiveData is never called.
And at connectionDidFinishDownloading destinationURL returns null.
I have no idea wat couses this problem and I would really appreciate some help.
the delegate
#import "NetWorkToGuiDelegate.h"
#implementation NetWorkToGuiDelegate
#synthesize data;
#synthesize caller;
- (id) init: (SEL) pointer :(NSObject *) c;
{
doWhenDone = pointer;
self.caller = c;
data = [[NSMutableData alloc]init];
return self;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responseText = [[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding];
NSLog(#"%#",responseText);
}
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL
{
NSLog(#"post download finished");
data = [NSData dataWithContentsOfURL:destinationURL];
NSLog(#"data: %#",data);
NSLog(#"URLconnection %#", connection.currentRequest);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[caller performSelector:doWhenDone withObject:data];
#pragma clang diagnostic pop
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.data setLength:0];
NSHTTPURLResponse *resp= (NSHTTPURLResponsae *) response;
NSLog(#"got responce with status %d",[resp statusCode]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d
{
NSLog(#"data recieved %#",d);
[self.data appendData:d];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error", #"")
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK", #"")
otherButtonTitles:nil] show];
NSLog(#"failed");
}
// Handle basic authentication challenge if needed
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
NSString *username = #"username";
NSString *password = #"password";
NSURLCredential *credential = [NSURLCredential credentialWithUser:username
password:password
persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
}
#end
the call
NetWorkToGuiDelegate *nwgd = [[NetWorkToGuiDelegate alloc] init:#selector(login:) :self];
NSString *stringURL = [NSString stringWithFormat:#"%#%#%#%#", dk.baseURL, #"menu?code=",dk.loginCode,#"&v=1"];
NSURL *url = [NSURL URLWithString:stringURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:nwgd];
[urlConnection start];
I'll just add that the call happens on the main thread
Actually there is a lot of points to make the answer of this question and there are so many questions on SO itself
Go through this nice post
And a must Read doc from apple itself.(contains code samples and explanations)
Hope this will solve the problems for you.
EDIT
-(void)startAConnection
{
// Create the request.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.apple.com/"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
// Create the NSMutableData to hold the received data.
// receivedData is an instance variable declared elsewhere.
receivedData = [NSMutableData data];
} else {
// Inform the user that the connection failed.
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// This method is called when the server has determined that it
// has enough information to create the NSURLResponse.
// It can be called multiple times, for example in the case of a
// redirect, so each time we reset the data.
// receivedData is an instance variable declared elsewhere.
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
// receivedData is an instance variable declared elsewhere.
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
// inform the user
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[receivedData length]);
}
Call startAConnection to start the process
NOTE: Don't forget <NSURLConnectionDelegate> in the .h
I have a web service I am working with a url such as
//myurl/index.jsp?user_name=bob&user_pwd=new
as you can see the username has been set as "bob" and password "new". The site give this json file when entered,
[{"success":"1"}]
How do you implemented it on xcode, where when a user enters "bob" as username and "new" as password it should lead to the next controller. How do can I achieve that ?
I followed this tutorial though it's not quite the same, how do you do this. Thanks.
Use a navigation controller and set you view controller as the rootViewController. Then after the user has entered the credentials push the new view controller onto the navigation stack.
Get the value of success from json response. If it is equal to 1 then push to next controller else do nothing.
In Following code you can pass data by either GET or POST method … use any one (As You Wish)
-(void) sendRequest
{
//////////////////////////// GET METHOD /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NSString *strURL=[NSString stringWithFormat:#"http://myurl/index.jsp?user_name=bob&user_pwd=new"];
self.request=[NSURLRequest requestWithURL:[NSURL URLWithString:strURL]];
self.nsCon=[[NSURLConnection alloc] initWithRequest:request delegate:self];
//////////////////////////// POST METHOD /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NSString *postString = [NSString stringWithFormat:#"&user_name=bob&user_pwd=new"];
NSString *url = [NSString stringWithFormat:#"http://myurl/index.jsp/"];
self.request =[NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
[self.request setHTTPMethod:#"POST"];
[self.request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if(self.nsCon)
{
self.receivedData=[[NSMutableData alloc] init];
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error",#"") message:NSLocalizedString(#"Not Connected !!",#"") delegate:nil cancelButtonTitle:NSLocalizedString(#"OK",#"") otherButtonTitles:nil];
[alert show];
[alert release];
}
}
#pragma mark -
#pragma mark - Connection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[self.responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[GeneralClass stopHUD];
NSLog(#"Connection failed.");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Error",#"") message:NSLocalizedString(#"Connection failed!",#"") delegate:nil cancelButtonTitle:NSLocalizedString(#"OK",#"") otherButtonTitles:nil];
[alert show]; alert = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responseString = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
NSMutableDictionary *receivedData = [responseString JSONValue];
if([[receivedData objectForKey:#"success"] isEqualToString:#"1"])
{
MainDetailViewController *mdController = [[MainDetailViewController alloc] init];
[self.navigationController pushViewController:mdController animated:YES];
}
else
{
NSLog(#"%#",receivedData);
}
}
Post login data
NSString *soapMsg = [NSString stringWithFormat:#"&data={\"LoginUser\":[{\"UserName\":\"%#\",\"Password\":\"%#\"}]}",firstname.text, password.text];
NSHTTPURLResponse *response;
NSData *myRequestData = [ NSData dataWithBytes: [ soapMsg UTF8String ] length: [ soapMsg length ] ];
NSString *postLength = [NSString stringWithFormat:#"%d", [myRequestData length]];
NSMutableURLRequest *request = [ [ NSMutableURLRequest alloc ] initWithURL: [ NSURL URLWithString:#"http://myurl/index.jsp"]];
[request setHTTPMethod: #"POST" ];
[request setHTTPBody: myRequestData ];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: myRequestData];
NSURLConnection *myConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
Receive and vaild json data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *responseString = [[NSString alloc] initWithData:WebXmlData encoding:NSUTF8StringEncoding];
NSDictionary *results = [responseString JSONValue];
BOOL success = [[results objectForKey:#"success"] boolValue];
if (success) {
ViewController *viewController =[[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
[self.navigationController pushViewController:viewController animated:YES];
}
}
Not quite the answer you are looking for but this is more a recommendation for what should you use.
I use github link for Network related activities.
They have nice documentation and very easy to use (uses blocks)
NSDictionary *paramsDictionary = [NSDictionary dictionaryWithObjectsAndKeys:#"user",#"client_id",#"password",#"new", nil];
[[YourAFHttpClientExtenstion sharedInstance] postPath:LOGIN_PATH parameters:paramsDictionary success:^(AFHTTPRequestOperation *operation, id responseObject) {
//handle success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// handle error.
}];
YourAFHttpClientExtenstion is extending AFHttpClient and adds a convening method of shared instance and implements initWithBaseUr:
I am new in objective C. I have done app in j2me and android using below code. I m trying same to consume web service through objective C but not getting success. It will be great if anyone guide me.
Thanks.
public static String RetriveData(String myStr)
{
String result1 = "-1";
Object ob1 = new Object();
ob1 =MyStr;
SoapObject rpc = new SoapObject("http://abcd.com/", "MyMethod");
rpc.addProperty("Mystr", ob1.toString());
try
{
Object strdata = new HttpTransport("http://11.22.33.44/myService.asmx", "http://abcd.com/" + "MyMethod").call(rpc);
result1 = strdata.toString().trim();
}
catch (Exception ex)
{
System.out.println("In catch block :" +ex);
}
return result1;
}
I am trying same through objective C as below but getting error.
NSURL *url = [NSURL URLWithString:#"http://11.22.33.44/MyService.asmx"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
NSString *msgLength = [NSString stringWithFormat:#"%d", [soapMessage length]];
//
//[theRequest addValue: #"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest addValue: #"http://abcd.com/MyMethod" forHTTPHeaderField:#"SOAPAction"];
//[theRequest addValue: msgLength forHTTPHeaderField:#"Content-Length"];
[theRequest addValue:#"MyStr" forHTTPHeaderField:#"MyStr"];
[theRequest setHTTPMethod:#"POST"];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if( theConnection )
{
webData = [[NSMutableData data] retain];
}
else
{
NSLog(#"theConnection is NULL");
}
[nameInput resignFirstResponder];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[webData setLength: 0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"ERROR with theConenction");
[connection release];
[webData release];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"DONE. Received Bytes: %d", [webData length]);
NSString *theXML = [[NSString alloc] initWithBytes: [webData mutableBytes] length:
[webData length] encoding:NSUTF8StringEncoding];
NSLog(theXML);
[theXML release];
if( xmlParser )
{
[xmlParser release];
}
xmlParser = [[NSXMLParser alloc] initWithData: webData];
[xmlParser setDelegate: self];
[xmlParser setShouldResolveExternalEntities: YES];
[xmlParser parse];
[connection release];
[webData release];
}
My personal recommendation is to use ASIHttpRequest. I consume web services (both .NET and PHP) with it and it seems much easier and straightforward to use in most cases.
Just include the ASIHttpRequest classes and the MBProgressHUD (If you want to use it)
Here is what I use to do it:
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"Connecting to Server";
// Start request
NSURL *url = [NSURL URLWithString:#"http://mydomain/MyWebService.asmx/MyMethod"];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setValidatesSecureCertificate:NO];
// Now setup the Request
[request setPostValue:#"MyValue1" forKey:#"WebServiceArg1"];
[request setPostValue:#"MyValue2" forKey:#"WebServiceArg2"];
[request setDelegate:self];
[request startAsynchronous];
Now use the delegate methods to check and consume the response from the web service:
#pragma mark - ASIHttpRequest Delegate Methods
- (void)requestFinished:(ASIHTTPRequest *)request
{
[MBProgressHUD hideHUDForView:self.view animated:YES];
if (request.responseStatusCode == 200) {
NSString *responseString = [request responseString];
// Do something with this, create an array or dictionary depending on how the return data is structured (this assumes you are using a JSON formatted return string btw
}
else {
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:#"Connection Error"
message:#"My Message"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[myAlert show];
}
} else {
NSLog(#"Error finishing request");
}
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
[MBProgressHUD hideHUDForView:self.view animated:YES];
// Standard UIAlert Syntax
UIAlertView *myAlert = [[UIAlertView alloc]
initWithTitle:#"Connection Error"
message:#"Unable to establish connection"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[myAlert show];
NSError *error = [request error];
NSLog(#"%#",error.localizedDescription);
}
There are many ways to do it but this is what I would use.
i get the follwing error below when i run the program given below
Error:
Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x5948b80 {NSUnderlyingError=0x5948ac0 "bad URL", NSLocalizedDescription=bad URL}
wat i need to do plz suggest me
thank u..
the code is given below
#implementation WebSampleViewController
- (void)viewDidLoad
{
[super viewDidLoad];
dataWebService = [[NSMutableData data] retain];
NSMutableURLRequest *request = [[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#" http://www.googleapis.com/customsearch"]] retain];
NSURLConnection *myConnection = [NSURLConnection connectionWithRequest:request delegate:self];
[myConnection start];
[super viewDidLoad];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[dataWebService setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[dataWebService appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSString *responseString = [[NSString alloc] initWithData:dataWebService encoding:NSUTF8StringEncoding];
NSLog(#"Response: %#",responseString);
[responseString release];
[dataWebService release];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"Error during connection: %#", [error description]);
}
You should not retain request instance of type NSMutableURLRequest.
You have an leading white space in your String URL.
Use the below code .
NSMutableURLRequest *request = [[NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://www.googleapis.com/customsearch"]];
I think, you should check your URL , I give the same "Not Found" as on iPhone.
Try it without the space at the beginning of your URL string.
You have to remove whitespace in your url
I am trying to get an NSURLConnection to work in my app. I have followed apple's code almost exactly but it doesn't seem to work. The NSURLConnection is inside of a method called, downloadSave. This method runs properly through the end, and my log indicates, "Connection Exists" - however nothing happens after that as if none of the delegate methods get called.
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
NSString *tempString = [[NSString alloc]initWithFormat:#"http://www.myWebsite.com/%#.jpg",chartFileName];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:tempString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
mutableData = [[NSMutableData data] retain];
self.image = nil;
NSLog(#"connection exists");
} else {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Connection Error" message:#"There was an error contacting the servers. Please try again." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
[activityIndicator stopAnimating];
}
[pool drain];
[pool release];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(#"got to connection did receive response");
[mutableData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutableData appendData:data];
NSLog(#"got some data were at %i",mutableData.length);
}
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
[connection release];
// receivedData is declared as a method instance elsewhere
self.mutableData = nil;
NSLog(#"Connection failed! Error - %# %#",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[mutableData length]);
//more code follows to display the downloaded image
}
The only thing that appears in the log is: "Connection Exists"
I can only guess by your code that downloadSave in called in a separate thread as you have an NSAutoReleasePool (not saying thats what your doing but its likely). NSURLConnection can only respond to the delegate methods in the main thread when it is initialised in the main thread.
As NSURLConnection already is a threaded delegate call you shouldn't need to create it in thread. If you need to thread it for some reason you should be able to use
NSError *error;
NSURLResponse *response;
NSData *connectionData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
And that should return the data to the child thread.