I have trouble finding info on this topic. Please help me out here.
I need to pass arguments via POST or GET method to my web server and get a reply.
Basically, if using GET method, I want to do something like server.com/?user=john&password=smith and receive the dynamically generated HTML code that is done with my php script. All this without using the web browser on my app.
How is it usually done?
You'll want to look into NSMutableURLRequest and NSURLConnection.
For example, you could use them like this do to a GET request to your server:
- (void)loginUser:(NSString *)username withPassword:(NSString *)password {
// GET
NSString *serverURL = [NSString stringWithFormat:#"http://yourserver.com/login.php?user=%#&pass=%#", username, password];
NSURL *url = [NSURL URLWithString:serverURL];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:req delegate:self];
if (connection) {
connectionData = [[NSMutableData alloc] init];
}
}
This will send an asynchronous GET request to your server with the query string containing username and password.
If you want to send username and password using a POST request, the method would look something like this:
- (void)loginUser:(NSString *)username withPassword:(NSString *)password {
// POST
NSString *myRequestString = [NSString stringWithFormat:#"user=%#&pass=%#",username,password];
NSData *myRequestData = [NSData dataWithBytes: [myRequestString UTF8String] length: [myRequestString length]];
NSURL *url = [NSURL URLWithString:#"http://yourserver.com/login.php"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req setHTTPMethod: #"POST"];
[req setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
[req setHTTPBody: myRequestData];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:req delegate:self];
if (connection) {
connectionData = [[NSMutableData alloc] init];
}
}
In order to get the response from the server, you will need to implement the NSURLConnection delegate methods, for example:
#pragma mark -
#pragma mark NSURLConnection delegate methods
#pragma mark -
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
// Called if you have an .htaccess auth. on server
NSURLCredential *newCredential;
newCredential = [NSURLCredential credentialWithUser:#"your_username" password:#"your_password" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[connectionData setLength: 0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[connectionData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[connectionData release];
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *content = [[NSString alloc] initWithBytes:[connectionData bytes]
length:[connectionData length] encoding: NSUTF8StringEncoding];
// This will be your server's HTML response
NSLog(#"response: %#",content);
[content release];
[connectionData release];
}
References:
NSMutableURLRequest Class Reference
NSURLConnection Class Reference
Hope this helps :)
Usually this is done using a NSURLConnection. You can also use NSString's method stringWithContentsOfURL.
Related
I am trying to login a server by sending my username and password by POST method by NSURLConnection on objective-c but I get this from my NSLog
NSLog:
NSLog:
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",string);
What it writes to the console:
404 Not Found
Not Found
Sorry!The page requested was not found.
Why does this happens? Why do I get Not Found page instead of the index page? What do I do wrong? By the way I am trying to connect https not http I don't know does Here is the source code:
#interface ProjectViewController ()
#property NSURLConnection * urlConnection;
#property NSMutableData * responseData;
#end
#implementation ProjectViewController
#synthesize responseData =_responseData;
- (IBAction)LoginButton:(UIButton *)sender {
NSMutableURLRequest *request = nil;
request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://loginpage.com"]];
NSString *post = [NSString stringWithFormat:#"sid=%#&PIN=%#", #"username", #"password"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setValue:[NSString stringWithFormat:#"%d", [postData length]] forHTTPHeaderField:#"Content-Length"];
[request setTimeoutInterval: 15];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[_urlConnection start];
//[self performSegueWithIdentifier:#"LoginComplete" sender:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.responseData appendData:data];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#",string);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//Oops! handle failure here
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
//NSDictionary *headerFields = [(NSHTTPURLResponse*)response allHeaderFields]; //This would give you all the header fields;
//NSLog(#"%#",headerFields);
}
}
#end
What I just recognized is if I put the part of POST request in to comment it prints the page source to the console but of course I can't send my username and password to the server. I just get the login page's source code but I want to get the source code after I login. Actually I want to redirect to another page by using this session.
This part:
NSString *post = [NSString stringWithFormat:#"sid=%#&PIN=%#", #"username", #"password"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setValue:[NSString stringWithFormat:#"%d", [postData length]] forHTTPHeaderField:#"Content-Length"];
[request setTimeoutInterval: 15];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
is the certificate used on the website self signed? did you try to make the request in a webview to see if it works there? not in an nsurlrequest?
try this response maybe it will give you some hints.
I would like to know how do I get a return value 1 or 0 only.... back from an URL request asynchronously.
currently I do it in this way:
NSString *UTCString = [NSString stringWithFormat:#"http://web.blah.net/question/CheckQuestions?utc=%0.f",[lastUTCDate timeIntervalSince1970]];
NSLog(#"UTC String %#",UTCString);
NSURL *updateDataURL = [NSURL URLWithString:UTCString];
NSString *checkValue = [NSString stringWithContentsOfURL:updateDataURL encoding:NSASCIIStringEncoding error:Nil];
NSLog(#"check Value %#",checkValue);
this works, however it is blocking my main thread till I got a reply back from the URL, how do I set it so it will do it in a another thread instead of the main thread ?
EDIT: ANSWER
I end upcalling my function with this, it works well :)
[self performSelectorInBackground:#selector(shouldCheckForUpdate) withObject:nil];
you can use NSURLConnection class
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
[[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
and handle its response and errors using its delegate methods.
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
You can find implementation of NSURLConnection
Apple docs: Using NSURLConnection
How To Use iOS NSURLConnection By Example
Edit: Although NSURLConnection is provided by apple is more recommended way of placing URL request. But I found AFNetworking library very time saving, easy to implement and robust yet simple as third party implementation. You should give it a try.
try this :
.h:
NSMutableData *responseData;
.m:
- (void)load
{
NSURL *myURL = [NSURL URLWithString:#"http://www.example.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[responseData release];
[connection release];
[textView setString:#"Unable to fetch data"];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[responseData
length]);
NSString *txt = [[[NSString alloc] initWithData:responseData encoding: NSASCIIStringEncoding] autorelease];
}
Use NSURLConnection and make your request.
Then you may start synchronous or asynchronous connection with NSURLConnection's methods :
Loading Data Synchronously
+ sendSynchronousRequest:returningResponse:error:
Loading Data Asynchronously
+ connectionWithRequest:delegate:
– initWithRequest:delegate:
– initWithRequest:delegate:startImmediately:
– start
Check the NSURLConnection class in Apple Developer API Reference.
Shamelessly copy from https://gist.github.com/knmshk/3027474. All credits go to https://gist.github.com/knmshk.
xmlData = [[NSMutableData alloc] init];
NSURL *url = [NSURL URLWithString:
#"http://forrums.bignerdranch.com/smartfeed.php?"
#"limit=NO_LIMIT&count_limit20&sort_by=standard&"
#"feed_type=RSS2.0&feed_style=COMPACT"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[NSURLConnection sendAsynchronousRequest:request
queue:queue
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error){
if (error) {
xmlData = nil;
NSLog(#"error:%#", error.localizedDescription);
}
[xmlData appendData:data];
}];
There is an example in the iOS XCode documentation called LazyTableImages. This does an asynchronous URL as well as asynchronous image load into UITableView cells displayed on the screen after scrolling stops. Excellent example of protocols, asynchronous data handling, etc.
I have a problem now. I need to pass an transactionID and an user password to a rest service and it is suppose to return me a true/false value (in XML format). However, it is consistently returning me (null).. I am totally lost some one please help.
NSString *urlString = [NSString stringWithFormat:#"https://10.124.128.93:8443/axis2/services/C3WebService/completeWithdrawal Transaction?transactionId=%#&password=%#", _transactionID.text, _userPassword.text];
NSURL *url = [[NSURL alloc] initWithString:urlString];
NSString *result = [[NSString alloc] initWithContentsOfURL:url];
NSLog(#"%#",result );
My result is constantly returning me null. How do i continue from here?
.h:
NSMutableData *responseData;
.m:
- (void)load {
NSURL *myURL = [NSURL URLWithString:#"https://10.124.128.93:8443/axis2/services/C3WebService/completeWithdrawal Transaction?transactionId=%#&password=%#", _transactionID.text, _userPassword.text];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[responseData release];
[connection release];
[textView setString:#"Unable to fetch data"];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[responseData
`enter code here` length]);
NSString *txt = [[[NSString alloc] initWithData:responseData encoding: NSASCIIStringEncoding] autorelease];
}
Consider using NSURLConnection which has a callback for the result and also a callback to get detailed error details. It als doesn't execute on the UI thread (doesn't hang UI during the request).
NSURL *url = [NSURL URLWithString:#"http://www.mysite.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:#"GET"];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
Then you can implement the delegate methods to get the error, the data and other details:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void) connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString* responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"result: %#", responseString);
[responseString release];
}
- (void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"error - read error object for details");
}
You might try using "initWithContentsOfURL:encoding:error:" instead and check "error". Also, use Charles or other http sniffer and compare results to a straight browser request ( did you check results in a browser?)
I need to connect to a server without typing "http://". I have to get only the server name and port number from the user. With this, I should be able to connect to a particular server...
In its simplest form, it looks something like this:
- (void)loadHostName:(NSString *)hostName onPort:(NSInteger)portNumber {
responseData = [[NSMutableData alloc] init];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://%#:%i", hostName, portNumber]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[connection release];
}
- (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(#"Oh noes! %#", [error localizedDescription]);
[responseData release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// Do something with the data, like load it in a web view.
[webView loadData:responseData MIMEType:#"text/html" textEncodingName:#"utf-8" baseURL:nil];
[responseData release];
}
In production code, you should handle cache requests, authentication challenges etc. (see the messages on NSURLConnection), but the above example will send an HTTP request and load it into a web view.
Try this,
NSURL *aUrl = [NSURL URLWithString:[NSString stringWithFormat:#"http://%#:%i", hostName, portNumber]];
NSURLRequest *request = [NSURLRequest requestWithURL:aUrl
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLResponse *resp = nil;
NSError *err = nil;
NSData *response = [NSURLConnection sendSynchronousRequest: theRequest returningResponse: &resp error: &err];
NSString * theString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
[resp release];
[err release];
NSLog(#"response: %#", theString);
well you can hardcode HTTP:// with the server name
example
NSString *serverName = "stackoverflow.com";
NSNumber *portNumber = 10;
NSString *finalYrl = [NSString StringWithFormat:#"HTTP://%#:%#",serverName , portNumber];
I'm trying to get a small twitter client running and I ran into a problem when testing API calls that require authentication.
My password has special characters in it, so when I try to use the following code it doesn't work.
NSString *post = [NSString stringWithFormat:#"status=%#", [status stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"http://%#:%##%#/statuses/update.json", username, password, TwitterHostname]];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSURLResponse *response;
NSError *error;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
I started looking into base64 and putting the authentication into the headers. I found Dave Dribin's post on his base64 implementation, and it seemed to make sense. However when I tried to use it the compiler started complaining about how it couldn't find the openssl libraries. So I read that I needed to link in the libcrypto library, but it doesn't seem to exist for iphone.
I've also read people saying that apple won't allow apps that use crypto libraries, which doesn't make sense to me.
So now I'm kinda stuck and confused. What's the easiest way to get basic authentication into my app?
Cheers
Two things. Firstly you have to use the async methods rather than the synchronous/class method.
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:req]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
// create the connection with the request
// and start loading the data
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
The authentication is managed by implementing this method in your delegate:
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
And you'll probably also need to implement these methods too:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
Using the async method tends to give a better user experience anyway so despite the extra complexity is worth doing even without the ability to do authentication.
You can directly aslo write download the username & password in main URL i.e https://username:password#yoururl.com/
First of all you need to call NSURLConnection Delegate file:-
(BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
{
return YES;
}
and then call
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
{
if ([challenge previousFailureCount] == 0)
{
NSURLCredential *newCredential;
newCredential = [NSURLCredential credentialWithUser:#"username"
password:#"password"
persistence:NSURLCredentialPersistenceForSession];
NSLog(#"NEwCred:- %# %#", newCredential, newCredential);
[[challenge sender] useCredential:newCredential forAuthenticationChallenge:challenge];
}
else
{
[[challenge sender] cancelAuthenticationChallenge:challenge];
NSLog (#"failed authentication");
}
}