iOS POST request parameters random crash when connecting to Zend server - ios

This question is related to this other one: Zend getParameters not returning what is in url route
The problem I'm facing is that, randomly, the Zend server does not get the parameters that are in the route, causing the login of my app crash. I.e., sometimes when printing the getParams(); function I get the user email as following:
Array (
[email] = user#email.com
(...)
)
This works fine, but some other times I get this:
Array (
[user#email.com] = 2.874983 //Longitude
(...)
)
Causing the crash of the login action.
This could be a fault in the server side or in the client side. I've put an NSLog to print the NSMutableURLRequest each time the server gets called, and I've seen that the request url is always well formed. Maybe this is a coincidence, I don't know, but sometimes trying to solve this issue I've changed the request code and it was temporarily fixed. But then, after some requests, the error was back.
The following snippet represents the code I'm using to connect to the server:
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[self._url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSMutableString *values = nil;
if ( params ) {
NSDictionary *parameters = params;
values = [[NSMutableString alloc] init];
for ( NSString* key in parameters ) {
NSMutableString *value = [[NSMutableString alloc] init];
[value appendString:key];
[value appendString:#"="];
[value appendString:[self urlEncodeValue:[parameters valueForKey:key]]];
[value appendString:#"&"];
[values appendString:value];
}
}
NSData *postData = [values dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *postLenght = [NSString stringWithFormat:#"%d", [postData length]];
if ( cookies ) {
NSDictionary *cooks = cookies;
for ( NSString* cookie in cooks) {
NSMutableString *ck = [[NSMutableString alloc] initWithString:cookie];
[ck appendString:#"="];
[ck appendString:[cooks valueForKey:cookie]];
[theRequest addValue:ck forHTTPHeaderField:#"Cookie"];
}
}
[theRequest setHTTPMethod:self._method];
if ( values ) {
[theRequest setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody: postData];
[theRequest setValue:postLenght forHTTPHeaderField:#"Content-Length"];
}
// create the connection with the request
// and start loading the data
NSLog(#"%#", theRequest);
NSURLConnection *theConnection =[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
Another important thing is that the login sends both latitude and longitude values, and it seems that it's crashing when some of those values changes.

I've solved this problem and I've posted the solution here: Zend getParameters not returning what is in url route
It was a memcached configuration problem, nothing to do with the iOS client application.

Related

Call function on Server from iOS app - Objective C

If you are familiar with Parse.com's Javascript SDK, this is what I am trying to do for my own server for my iOS app (Objective-c). I want to be able to send some a string to the function that is on my server, have the server run its function and then return a string to the app or some xml or JSON data.
Is this even possible?
I am new to doing something like this having an app make a call to a server. I have looked into opening a port on my server, but have been unable to find a way to receive data back to the iOS app. (I found this lib but its for OS X https://github.com/armadsen/ORSSerialPort). Also Im not sure if I have a function run with an open port on the server. So how can I set it up so I can make a call to my server and run a function?
Any help would be much appreciated.
You just need to POST data to your server.
Port could be anything you want.
Host your script with a domain url so that you can make network request publicly.
You can try this function:
-(NSData *)post:(NSString *)postString url:(NSString*)urlString{
//Response data object
NSData *returnData = [[NSData alloc]init];
//Build the Request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"POST"];
[request setValue:[NSString stringWithFormat:#"%lu", (unsigned long)[postString length]] forHTTPHeaderField:#"Content-length"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
//Send the Request
returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil];
//Get the Result of Request
NSString *response = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];
bool debug = YES;
if (debug && response) {
NSLog(#"Response >>>> %#",response);
}
return returnData;
}
And here is how you use it:
NSString *postString = [NSString stringWithFormat:#"param=%#",param];
NSString *urlString = #"https://www.yourapi.com/yourscript.py";
NSData *returnData = [self post:postString url:urlString];
PHP
<?php
$response=array();
if(isset($_POST['param'])){
$response['success'] = true;
$response['message'] = 'received param = '.$_POST['param'];
}else{
$response['success'] = false;
$response['message'] = 'did not receive param';
}
$json = json_encode($response);
echo $json;

NSMutableURLRequest not changing HTTPMethod

I have the following method in XCode:
- (void)makeRequest:(NSString *)wPin withMethod:(NSString *)HTTPMethod passValue:(NSString *)wVal {
#try {
NSString *params = #"";
NSString *postString;
NSData *postData;
NSString *method;
if ([HTTPMethod isEqualToString:#"GET"]) {
params = [NSString stringWithFormat:#"?pin=%#", wPin];
method = #"Retrieving data from";
} else {
postString = [NSString stringWithFormat:#"pin=%#&val=%#", wPin, wVal];
postData = [postString dataUsingEncoding:NSUTF8StringEncoding];
method = [NSString stringWithFormat:#"Passing '%#' to", postString];
}
NSString *requestURL = [NSString stringWithFormat:#"%#%#", homeURL, params];
NSLog(#"%# '%#'", method, requestURL);
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:requestURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:0];
NSString *postLength = [[NSString alloc] initWithFormat:#"%lu", (unsigned long)[postData length]];
[request setHTTPMethod:HTTPMethod];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSString *postBody = [[NSString alloc] initWithBytes: [request.HTTPBody bytes] length: [request.HTTPBody length] encoding:NSUTF8StringEncoding];
NSLog(#"%#", postBody);
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate: self];
if (conn) { //Makes connection
}
}
#catch (NSException *e) {
NSLog(#"Exception %#", e);
}
}
When I call this method using:
[self makeRequest:wPin withMethod:#"GET" passValue:#""];
My server logs a healthy GET request, and sends me back the right data, and I parse it... it works, no problem.
However, when I call this method using:
[self makeRequest:wPin withMethod:#"POST" passValue:wState];
My server still logs the request method as "GET". I've even tried setting the HTTPMethod directly:
[request setHTTPMethod:#"POST"];
And my server still logs a "GET" request.
FYI: I developed the same app in JavaScript, and everything works fine (Server handles GET and POST correctly).
Here is my app console output:
(on load)
2015-01-28 10:25:08.324 Switch[2977:132599] Retrieving data from '<my server>?pin=18'
2015-01-28 10:25:08.330 Switch[2977:132599] Retrieving data from '<my server>?pin=23'
2015-01-28 10:25:08.611 Switch[2977:132599] 18OFF
2015-01-28 10:25:08.626 Switch[2977:132599] 23ON
(when I send three POST requests)
2015-01-28 10:25:28.842 Switch[2977:132599] Passing 'pin=18&val=1' to '<my server>'
2015-01-28 10:25:28.843 Switch[2977:132599] pin=18&val=1
2015-01-28 10:28:12.189 Switch[2977:132599] Passing 'pin=18&val=0' to '<my server>'
2015-01-28 10:28:12.190 Switch[2977:132599] pin=18&val=0
2015-01-28 10:28:13.702 Switch[2977:132599] Passing 'pin=23&val=0' to '<my server>'
2015-01-28 10:28:13.703 Switch[2977:132599] pin=23&val=0
Also, when you see something like "pin=18&val=1" in the output, note that's just an NSLog of the postBody before it sends. That's not a server response, unlike the "18OFF" you see in the output.
Try changing encoding scheme,
[postString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
The problem was with the way the DNS works with my server. I have to circumvent port 80, so when my domain name is pointed to it's proper port to reach my router, I receive an "Object Moved" response from POST requests unless I enter my server's IP manually. This somehow means the POST request becomes a GET request before reaching my page. In using direct IP, the app works. I'll have to sort this issue out elsewhere. Thanks to all who tried helping!
(The good news is, NSMutableURLRequest works!)

Fetching an access token for youtube api iOS "Error" : "invalid_request"

I'm trying to get an access token for a youtube app for iOS. Here's the relevant code I have been using from my viewDidLoad method:
mAuth = [[GTMOAuth2Authentication alloc]init];
[mAuth setClientID:#"<MY CLIENT ID>"];
[mAuth setClientSecret:#"<MY CLIENT SECRET>"];
[mAuth setRedirectURI:#"urn:ietf:wg:oauth:2.0:oob"];
[mAuth setScope:#"https://gdata.youtube.com"];
[self.web loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://accounts.google.com/o/oauth2/auth?client_id=%#&redirect_uri=%#&scope=%#&response_type=code&access_type=offline", mAuth.clientID, mAuth.redirectURI, mAuth.scope]]]];
After this is called, the user has to grant access to their account, then I retrieve the auth code from the resulting page in the following code:
NSString *string = [self.web stringByEvaluatingJavaScriptFromString:#"document.title"];
if([string rangeOfString:#"Success"].location != NSNotFound){
NSLog(#"This is the code page");
NSString *importantCode = [[string componentsSeparatedByString:#"="] objectAtIndex:1];
NSLog(#"%#", importantCode);
if([self.defaults objectForKey:#"super important code"] == nil){
[self.defaults setObject:importantCode forKey:#"super important code"];
[self.defaults synchronize];
NSString *post = [NSString stringWithFormat:#"code=%#&client_id=%#&client_secret=%#&redirect_uri=%#&grant_type=code", [self.defaults objectForKey:#"super important code"], mAuth.clientID, mAuth.clientSecret, mAuth.redirectURI];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]init];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://accounts.google.com/o/oauth2/token"]]];
[request setHTTPMethod:#"POST"]; [request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
[self.web loadRequest:request];
}
[timer invalidate];
}
After that, I should be given the access token in response to my POST request, but instead I get a page that simply says:
{
"error" : "invalid_request"
}
Does anyone (see where I went wrong)/(know how to retrieve the access token)?
I’d be interested in knowing what the HTTP status code is... I suspect ”invalid_request” means 400, which almost always means there’s some irritating stupid little error in the way you composed your authent URI. I don’t know enough iOS/ObcJ to tell if you’ve properly URLescaped any funny characters in any of the parameter values, but it’s worth checking. Or a typo in one of the values, or an extra newline creeping in or something?
It was as simple as this, I had set the grant_type parameter to 'code' when it should have been 'authorisation_code' if you are reading this and you are using the youtube api, don't make the same mistake. If you're reading this and you're sending a POST request in general, this error "invalid_request" means that either you skipped one of the parameters you should have added, or you added it incorrectly.

Convert a Web service from GET to POST

I have created a web service to make a communication between an iOS application and a Joomla web site, and I used the GET method to communicate between the mobile application and the web service and also between the web service and the controller (PHP file that does the work and return the data) , but I didn't find how to convert the implementation to POST method here is the actual system :
ws.php : it's the web service (simple example )
<?php
$id = $_GET['id'] ; // get the data from the URL
// here i make testes
// then I redirect to the controller of the Joomla component that receive
// the call of the request the URL is actually the attribute "action" of
// an existing HTML Form that implement the login system, I added a
// parameter called web service to help me to modify the controller
// to make the difference between a normal call and a web service call
header("Location: index.php?option=com_comprofiler&task=login&ws=1&id=1");
?>
Controller.php : the receiver of the web service call and the web call (from browser)
<?php
// code added by me, in the existent controller of the component
// it was waiting for a form submitting, so I got to convert my data to POST here
if (isset($_GET['ws'])) // it's a web service call
{
$_POST['id'] = $_GET['id'] ;
// do the task ...
if ($correctLogin) // just an example
echo "1"
else
echo '0';
}
?>
I didn't put the real implementation, and it's just a simple example of the system, but it's the same
Call from the mobile
NSURL *url = [[NSURL alloc]initWithString:#"http://localhost/ws.php?id=1"];
NSData *dataUrl= [NSData dataWithContentsOfURL:url];
NSString *str = [[NSString alloc]initWithData:dataUrl
encoding:NSUTF8StringEncoding];
if(![str isEqualToString:#"0"])
NSLog(#"connected");
else
NSLog(#"not connected");
so I don't want to use the GET method, I just want to receive my data from the mobile using POST and also send the data to the controller using POST also, what is the best solution ?
If you want your app to send data using POST method, then I'm this code. I hope it will help.
It takes the data to be sent in dictionary object.
Ecodes the data to be sent as POST
and then returns the response (if you want the results in string format you can use [[NSString alloc] initWithData:dresponse encoding: NSASCIIStringEncoding]; when returning data)
-(NSData*) getData:(NSDictionary *) postDataDic{
NSData *dresponse = [[NSData alloc] init];
NSURL *nurl = [NSURL URLWithString:url];
NSDictionary *postDict = [[NSDictionary alloc] initWithDictionary:postDataDic];
NSData *postData = [self encodeDictionary:postDict];
// Create the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:nurl];
[request setHTTPMethod:#"POST"]; // define the method type
[request setValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
// Peform the request
NSURLResponse *response;
NSError *error = nil;
dresponse = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
return dresponse;
}
This method prepares the Dictionary data for POST
- (NSData*)encodeDictionary:(NSDictionary*)dictionary {
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in dictionary) {
NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *encodedKey = [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *part = [NSString stringWithFormat: #"%#=%#", encodedKey, encodedValue];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
}

password with percentage symbol always wrong iPhone

I'm developing an iPhone application in Xcode with a login function and I'm having trouble with the following code:
NSString *post = [NSString stringWithFormat:#"username=%#&password=%#",[NSString stringWithFormat:#"%#",username],password];
NSLog(post);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
[request setHTTPMethod:#"POST"];
[request addValue:[NSString stringWithFormat:#"%#",username] forHTTPHeaderField:#"username"];
[request addValue:password forHTTPHeaderField:#"password"];
[request setHTTPBody:postData];
action = #"token";
NSURLConnection *connection;
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
Now there is a member with the password %32dzs3* and the app always gives an error that the password is incorrect. When I NSLog the password it's indeed not the password I typed in the textfield. it looked like this: 50883393zs3* . I also tried this:
for(int i = 0; i < [password length];i++){
if([password characterAtIndex:i] == '%'){
NSString *temporarypw = [password substringWithRange:NSMakeRange(0, i)];
password = [NSString stringWithFormat:#"%#%%%%%#",temporarypw,[password substringWithRange:NSMakeRange((i+1), (password.length - i -1))]];
break;
}
}
this returns the password as %%%%32dzs3* and the password is right when I NSLog it. still the response is a wrong password response when I run the request. How can I fix this?
% is a special character in HTTP URLs. You need to escape it before creating the URL, also :, /, #, ;, and #. Fortunately NSString has a method to do it.
You probably need to escape the password correctly. See this question:
NSString method to percent escape '&' for URL

Resources