Attempting to send POST request to URL in iOS - ios

I'm trying to post to a webserver in iOS but am receiving a 404 error. The person I'm working with is able to post from a different system with the address and data in a single string:
http://xxx.xxx.xxx.xxx/api/message?salu=mr&firstname=john&lastname=smith&email=smith#testemail.com&country=usa&zipcode=99999&checkbox=y&messagelist=message&q1=1&q2=2&q3=3&q4=4&q5=5
I'm trying to do the same with the following code in Xcode:
NSString *body = [NSString stringWithFormat:#"message?salu=mr&firstname=john&lastname=smith&email=matt#testmail.com&country=usa&zipcode=99999&checkbox=y&messagelist=message&q1=1&q2=2&q3=3&q4=4&q5=5"];
NSData *data = [body dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [data length]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://xx.xxx.xxx.xxx/api"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:data];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSString *reply = [[NSString alloc] initWithBytes:[responseData bytes] length:[responseData length] encoding:NSASCIIStringEncoding];
NSLog(#"requestReply: %#", reply);
and the last few lines of 'reply' above from NSLog are:
<b> Description: </b>HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
<br><br>
<b> Requested URL: </b>/api<br><br>
</body>
However, I'm able to perform a 'GET' on the same address with the following code, where I receive the expected data:
NSMutableURLRequest *request2 = [[NSMutableURLRequest alloc] init];
[request2 setURL:[NSURL URLWithString:#"http://xx.xxx.xxx.xxx/api/message"]];
[request2 setHTTPMethod:#"GET"];
NSURLResponse *requestResponse;
NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request2 returningResponse:&requestResponse error:nil];
NSString *requestReply = [[NSString alloc] initWithBytes:[requestHandler bytes] length:[requestHandler length] encoding:NSASCIIStringEncoding];
NSLog(#"requestReply: %#", requestReply);
So the web server is functioning and it appears the problem lies in the way I'm posting. Does anyone have an idea of what I'm doing wrong?

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://xx.xxx.xxx.xxx/api"]];
Don't you notice that you should call NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://xx.xxx.xxx.xxx/api/message"]];
/message is part of path, not request body.
and look forward to use some ready framework, such as AFNetworking is.

You've taken the last path component of the request's URL, message, and put that into the body of the request. So, replace:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://xx.xxx.xxx.xxx/api"]];
with
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://xx.xxx.xxx.xxx/api/message"]];
Also, replace:
NSString *body = [NSString stringWithFormat:#"message?salu=mr&firstname=john&lastname=smith&email=matt#testmail.com&country=usa&zipcode=99999&checkbox=y&messagelist=message&q1=1&q2=2&q3=3&q4=4&q5=5"];
with:
NSString *body = [NSString stringWithFormat:#"salu=mr&firstname=john&lastname=smith&email=matt#testmail.com&country=usa&zipcode=99999&checkbox=y&messagelist=message&q1=1&q2=2&q3=3&q4=4&q5=5"];

Related

Send POST using NSURLConnection with HTTPS

I have been searching over the internet about the right configuration to send a POST to my server using HTTPS, some web pages say i need NSURLCredential and others say:
Just use a #"https://www.myhttpsite.com/" URL and it should work the same way as normal HTTP urls.
So, how is the right way? i need to send credentials of users from my iOS app to my server to authenticate them, so i need to protect this credentials with the HTTPS.
My server already works fine with the HTTPS using internet browsers.
So far what i have is this:
NSString *user = #"user";
NSString *pass = #"pass";
NSString *postData = [NSString stringWithFormat:#"user=%#&pass=%#", user, pass];
NSURL *url = [NSURL URLWithString:#"https://myserver.com"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = #"POST";
request.HTTPBody = [postData dataUsingEncoding:NSUTF8StringEncoding];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSString *strData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"data %#", strData);
}];
Found this to be a good example, why don't you try it out?
NSString *urlstring =[[NSString alloc] initWithFormat:#"userName=%#&password=%#",userName.text,password.text];
NSURL *url=[NSURL URLWithString:#"https://www.example.com/mobile/Login.php"];
NSData *postData = [urlstring dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[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];
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];
NSError *error;
NSURLResponse *resp;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&resp error:&error];
NSString *data=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];

Google Api getting an error

NSString *clientsec = #"my client sec";
NSString *clientid = #"client id";
NSString *grant = #"urn:ietf:params:oauth:grant-type:migration:oauth1";
NSString *post =[[NSString alloc] initWithFormat:#"client_secret=%#&grant_type=%#&client_id=%#",clientsec,grant,clientid];
NSLog(#"%#",post);
NSURL *url=[NSURL URLWithString:#"https://accounts.google.com/o/oauth2/token"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[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];
NSError *error;
NSURLResponse *response;
NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *data=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"%#",data);
i am posting the data like this but i am getting an error like this
"error" : "invalid_request"
can any one solve my problem ... Thanks in advance
This google API must contain 5 arguments.
code - The authorization code returned from the initial request
client_id - The client_id obtained during application registration
client_secret - The client secret obtained during application registration
redirect_uri - The URI registered with the application
grant_type - As defined in the OAuth 2.0 specification, this field must contain a value of authorization_code
Then your actual request might look like this
POST /o/oauth2/token HTTP/1.1
Host: accounts.google.com
Content-Type: application/x-www-form-urlencoded
code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&
client_id=8819981768.apps.googleusercontent.com&
client_secret={client_secret}&
redirect_uri=https://oauth2-login-demo.appspot.com/code&
grant_type=authorization_code
So you have to add code and redirect_uri parameters in your request.
I tried with this one, and worked:
NSString *urlString = #"https://accounts.google.com/o/oauth2/token";
NSURL *url=[NSURL URLWithString:urlString];
NSString *clientsec = #"my client sec";
NSString *clientid = #"client id";
NSString *grant = #"urn:ietf:params:oauth:grant-type:migration:oauth1";
NSString *post =[[NSString alloc] initWithFormat:#"client_secret=%#&grant_type=%#&client_id=%#",clientsec,grant,clientid];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%ld", [postData length]];
urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSMutableURLRequest* theRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[theRequest setTimeoutInterval:120.0f];
[theRequest setURL:url];
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[theRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[theRequest setHTTPBody:postData];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
NSLog(#"%#",responseData);
Output:
client_secret=my client
sec&grant_type=urn:ietf:params:oauth:grant-type:migration:oauth1&client_id=client
id 2013-12-10 19:10:07.283 AkbarVenkatConflict[18969:8c03] <7b0a2020
22657272 6f722220 3a202269 6e76616c 69645f63 6c69656e 74222c0a
20202265 72726f72 5f646573 63726970 74696f6e 22203a20 22426164
20726571 75657374 2e220a7d>

How to Use Cache Memory concept in objective-c

// Web service request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: urlLoc]];
NSString *postLength = [NSString stringWithFormat:#"%d", [requestData length]];
[request setHTTPMethod: #"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: requestData];
NSError *respError = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: &respError ];
//returndata is response of webservice
NSString *responseString = [[NSString alloc] initWithData:returnData encoding: NSUTF8StringEncoding];
NSDictionary *results = [responseString JSONValue] ;
NSLog(#"chat data- %#",results);
NSString *strResults = [results objectForKey:#"d"];
NSLog(#"result string is-%#",strResults);
this is the code that I am using for my Data fetching from web service. But i have to do this every time when come to this page.
Is that any method that can store my data in Cache memory so i need not to request every time.
I Am using
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
but i dont know how to use - (NSCachedURLResponse *) connection this method
thanks...
You need to use cache as of your needs according to this documentation: whenever you requesting a NSMutableURLRequest...
For Ex:
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReloadRevalidatingCacheData timeoutInterval:60];
For More details Kindly look into the Documentation

IOS to REST-ful MVC Api Service - [Get] works, but parameters don't reach server with [Post]

I think the title explains it. I can reach the Get functions on my api controllers just fine. I can reach the Post method, but my parameter (macAddress) is null. I've tried many variations of this code in xcode:
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",baseURL,controller]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request setHTTPMethod:#"POST"];
NSString *postString = #"macAddress=testestest";
NSData *myRequestData = [ NSData dataWithBytes: [ postString UTF8String ] length: [ postString length ] ];
[request setHTTPBody:myRequestData];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
and the controller:
public String Post([FromBody]string macAddress)
{
//......
}
(I'm aware that I'm using synchronous requests and nil response/errors, just trying to figure out this aspect)
Thanks for the help.
It looks like you have your *postString without the [NSString stringWithFormat method]. I use the following code with my own restful API.
NSString *deviceToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"rsdevicetoken"];
NSString *postString = [NSString stringWithFormat:#"token=%#&active=%#&draw=%#&result=%#&message=%#",deviceToken,allNotify, draw, results, message];
NSData *postData = [postString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"http://www.someurl.com/updateSubscriptions"]];
[request setHTTPMethod:#"POST"];
[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);
Hopefully this will help you.
It's a wild guess but if your macAddress post param has the following format: 01:23:45:67:89:ab you need to url encode the ':' to '%3A'.

NSMutableURLRequest transform to ASIFormDataRequest

I have writen the fellowing code:
NSString *urlString = [NSString stringWithFormat:ADDRESS,action];
postStr = #"user_name=Thomas Tan&phone=01234567891&password=123456";
NSData *myRequestData = [NSData dataWithBytes:[postStr UTF8String] length:[postStr length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody: myRequestData];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *responseString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(#"%#",responseString);
it works well,but now I want to use asihttprequest framework,so how to change the above code,I have writen the code,but it can't get the correct result and just get the server error infomation.so what's the problem?
NSString *urlString = [NSString stringWithFormat:ADDRESS,action];
NSURL *url = [NSURL URLWithString:urlString];
ASIFormDataRequest *requeset = [ASIFormDataRequest requestWithURL:url];
[requeset setRequestMethod:#"POST"];
[requeset setPostValue:#"Thomas Tan" forKey:#"user_name"];
[requeset setPostValue:#"01234567891" forKey:#"phone"];
[requeset setPostValue:#"123456" forKey:#"password"];
[requeset startSynchronous];
NSError *error = [requeset error];
if (!error) {
NSString *re = [requeset responseString];
NSLog(#"%#",re);
}
NSLog(#"%#",error);
thank you in advance.
UPDATE:
NSString *urlString = [NSString stringWithFormat:ADDRESS,action];
NSURL *url = [NSURL URLWithString:urlString];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setRequestMethod:#"POST"];
[request appendPostData:[#"user_name=Thomas Tan&phone=01234567891&password=123456" dataUsingEncoding:NSUTF8StringEncoding]];
[request startSynchronous];
NSError *error = [request error];
if (!error) {
NSString *re = [request responseString];
NSLog(#"%#",re);
}
NSLog(#"%#",error);
I use the above code ,It also can't get the same result,and error is not nil.
Your ASIHTTP code is not doing the same thing as your NSURLConnection code.
ASIFormDataRequest will automatically:
set the Content-Type header to application/x-www-form-urlencoded
URL-encoded your parameters
That's usually exactly what you want, but if you're getting the correct behavior with your NSURLConnection code and incorrect with ASIHTTP, then you need to change to a custom ASIHTTP POST and use ASIHTTPRequest, not ASIHTTPFormDataRequest, and then manually set the Conten-type back to application/x-www-form-urlencoded:
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setRequestMethod:#"POST"];
[request addRequestHeader:#"Content-Type" value:#"application/x-www-form-urlencoded"];
[request appendPostData:[#"user_name=Thomas Tan&phone=01234567891&password=123456" dataUsingEncoding:NSUTF8StringEncoding]];
Doing this, and inspecting exactly what was sent to the server using Wireshark, I can see that the POST data sent is still not quite identical (ASIHTTP on the left, NSURLConnection on the right):
But the content type, length, and actual data is identical.
At this point, I'd expect your server to return the same result.
If it still doesn't, you can edit the ASIhTTP request parameters to match.

Resources