Bad url request while sending GET request - iphone

http://<url>/<abc>.php?email=<email_id>&datadict=<json dictionary>&id=<id>
Above is my get request url i am sending in GET. But xcode is creating 'Bad Url' error.
I have already used NSUTF8StringEncoding for creating a valid url.
i am developing for ios 6.
Can anyone help me??
Following is my code :
serviceUrl = #"http://<url>/<abc>.php?
NSMutableString* theString = [NSMutableString string];
[theString appendString:[NSString stringWithFormat:#"%#email=",serviceUrl]];
[theString appendString:[NSString stringWithFormat:#"%#",[myDict objectForKey:#"email"]]];
[theString appendString:[NSString stringWithFormat:#"&datadict=%#&",[myDict objectForKey:#"confirmation"]]];
//paypal payment gateway confirmation in json
//NSString* udidEncoded = [[myDict objectForKey:#"udid"] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
[theString appendString:[NSString stringWithFormat:#"udid=%#",[[UIDevice currentDevice] identifierForVendor].UUIDString]];
NSLog(#"concat : %#", theString);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:theString] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:900.0];
return request;

Related

How to post a string to web server url in iphone sdk?

How can I post a string(i.e) a word to web server url in iphone sdk?
Some sample codes or tutorials would be appreciated.
Thanking you.
This may help you, although I havent tested it:
NSMutableString *httpBodyString;
NSURL *url;
NSMutableString *urlString;
httpBodyString=[[NSMutableString alloc] initWithString:#"Name=The Big Bopper&Subject=Hello Baby&MsgBody=...You knooow what I like...Chantilly lace..."];
urlString=[[NSMutableString alloc] initWithString:#"http://www.somedomain.com/contactform.php"];
url=[[NSURL alloc] initWithString:urlString];
[urlString release];
NSMutableURLRequest *urlRequest=[NSMutableURLRequest requestWithURL:url];
[url release];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:[httpBodyString dataUsingEncoding:NSISOLatin1StringEncoding]];
[httpBodyString release];
NSURLConnection *connectionResponse = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
if (!connectionResponse)
{
NSLog(#"Failed to submit request");
}
else
{
NSLog(#"--------- Request submitted ---------");
NSLog(#"connection: %# method: %#, encoded body: %#, body: %a", connectionResponse, [urlRequest HTTPMethod], [urlRequest HTTPBody], httpBodyString);
NSLog(#"New connection retain count: %d", [connectionResponse retainCount]);
responseData=[[NSMutableData data] retain];
NSLog(#"response", responseData);
}
Source: http://www.iphonedevsdk.com/forum/iphone-sdk-development/6341-help-executing-http-url-post-variables.html
You can post the string to webservice in so many ways, In those one is
Using Rest protocol:
It has two sub types, HTTP GET, HTTP POST. The Http Get is simple.
You can add the value to the attribute and you can directly call the service.
Check the following code.
NSString *url = #"http://123.456.789.0?action=get_movies";
Here the I am passing the get_movies string to the server to the action attribute.
and then follow the code for requesting to server.
NSURL *reqUrl = [[NSURL alloc] initWithString:url];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:reqUrl];
NSError *error;
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSStringEncoding responseEncoding = NSUTF8StringEncoding;
if ([response textEncodingName]) {
CFStringEncoding cfStringEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)[response textEncodingName]);
if (cfStringEncoding != kCFStringEncodingInvalidId) {
responseEncoding = CFStringConvertEncodingToNSStringEncoding(cfStringEncoding);
}
}
[reqUrl release];
NSString *dataString = [[NSString alloc] initWithData:data encoding:responseEncoding];
the dataString is the responseString from the server. You can use that.
Regards,
Satya.

Issue with HTTP request in Objective C

Iam trying to submit values to an external DB using http request
My code is below
NSString *post =[NSString stringWithFormat:#"user=%#&child=%#&content=%#",userId,childId, crackContent.text];
responseData = [[NSMutableData data] retain];
NSString *hostStr = #"http://myhost.com/addItem.php?";
post = [utilityObj getEncodedUrl:post];
hostStr = [hostStr stringByAppendingString:post];
NSLog(hostStr);
NSLog(hostStr);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:hostStr]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
My issue is that if any space contains any of the parameter it will not submitted, otherwise it is successfully submitted.
Help is highly appreciated.
You may get the parameter encoded before send.
NSString* escapedUrlString =
[unescapedString stringByAddingPercentEscapesUsingEncoding:
NSASCIIStringEncoding];
Alternative
NSString * escapedUrlString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unescapedString,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
kCFStringEncodingUTF8 );

How to send authenticated requests to Google Reader?

It seems that Google has disabled the old way of sending cookie SID to their Google Data Services, specifically Google Reader.
This way does not work at least for me:
//create request
NSString* content = [NSString stringWithFormat:#"accountType=HOSTED_OR_GOOGLE&Email=%#&Passwd=%#&service=ah&source=myapp", [loginView username].text, [loginView password].text];
NSURL* authUrl = [NSURL URLWithString:#"https://www.google.com/accounts/ClientLogin"];
NSMutableURLRequest* authRequest = [[NSMutableURLRequest alloc] initWithURL:authUrl];
[authRequest setHTTPMethod:#"POST"];
[authRequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-type"];
[authRequest setHTTPBody:[content dataUsingEncoding:NSASCIIStringEncoding]];
NSHTTPURLResponse* authResponse;
NSError* authError;
NSData * authData = [NSURLConnection sendSynchronousRequest:authRequest returningResponse:&authResponse error:&authError];
NSString *authResponseBody = [[NSString alloc] initWithData:authData encoding:NSASCIIStringEncoding];
//loop through response body which is key=value pairs, seperated by \n. The code below is not optimal and certainly error prone.
NSArray *lines = [authResponseBody componentsSeparatedByString:#"\n"];
NSMutableDictionary* token = [NSMutableDictionary dictionary];
for (NSString* s in lines) {
NSArray* kvpair = [s componentsSeparatedByString:#"="];
if ([kvpair count]>1)
[token setObject:[kvpair objectAtIndex:1] forKey:[kvpair objectAtIndex:0]];
}
//if google returned an error in the body [google returns Error=Bad Authentication in the body. which is weird, not sure if they use status codes]
if ([token objectForKey:#"Error"]) {
//handle error
};
And the request:
TTURLRequest *request = [TTURLRequest requestWithURL:url delegate:self];
request.cachePolicy = cachePolicy;
request.cacheExpirationAge = TT_CACHE_EXPIRATION_AGE_NEVER;
NSString *cookieHeader = [NSString stringWithFormat:#"Name=SID;SID=%#;Domain=.google.com;Path=/;Expires=160000000000", sid];
[request setValue:cookieHeader forHTTPHeaderField:#"Cookie"];
[request setHttpMethod:#"GET"];
[request setValue:#"myapp" forHTTPHeaderField:#"User-agent"];
Changing to use the GoogleLogin auth=xxx gives me a NSURLErrorDomain 401
TTURLRequest *request = [TTURLRequest requestWithURL:url delegate:self];
request.cachePolicy = cachePolicy;
request.cacheExpirationAge = TT_CACHE_EXPIRATION_AGE_NEVER;
NSString *authorizationHeader = [NSString stringWithFormat:#"GoogleLogin auth=%#", auth];
[request setValue:authorizationHeader forHTTPHeaderField:#"Authorization"];
[request setHttpMethod:#"GET"];
[request setValue:#"myapp" forHTTPHeaderField:#"User-agent"];
The result is always the 401 error code. Could someone show me how to fix in this specific case? Thank you in advance.
Error Domain=NSURLErrorDomain Code=401 "Operation could not be completed. (NSURLErrorDomain error 401.)"
Error description: Operation could not be completed. (NSURLErrorDomain error 401.)
Changing the body of the POST solves the 401 error. Differences are in the service, source & continue.
NSString* content = [NSString stringWithFormat:#"Email=%#&Passwd=%#&service=reader&source=yourapp&continue=http://www.google.com", username, password];

a "+" sign in email address

I need to submit an email address with a "+" sign and validate in on server. But server receives email like "aaa+bbb#mail.com" as "aaa bbb#mail.com".
I send all data as POST request with following code
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", url, #"/signUp"]];
NSString *post = [NSString stringWithFormat:#"&email=%#&userName=%#&password=%#",
user.email,
user.userName,
user.password];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSData* data = [self sendRequest:url postData:postData];
post variable before encoding has value
&email=aaa+bbb#gmail.coma&userName=Asdfasdfadsfadsf&password=sdfasdf
after encoding it is same
&email=aaa+bbb#gmail.coma&userName=Asdfasdfadsfadsf&password=sdfasdf
Method I use to send request looks like following code:
-(id) sendRequest:(NSURL*) url postData:(NSData*)postData {
// Create request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
NSString *postLength = [NSString stringWithFormat:#"%d",[postData length]];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Current-Type"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURLResponse *urlResponse;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:nil];
[request release];
return data;
}
The email, user name and password need to be escaped by -stringByAddingPercentEscapesUsingEncoding:.
NSString *post = [NSString stringWithFormat:#"&email=%#&userName=%#&password=%#",
[user.email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
...
However, this won't escape the + since it is a valid URL character. You may use the more sophiscated CFURLCreateStringByAddingPercentEscapes, or for simplicity, just replace all + by %2B:
NSString *post = [NSString stringWithFormat:#"&email=%#&userName=%#&password=%#",
[[user.email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
stringByReplacingOccurrencesOfString:#"+" withString:#"%2B"], ...
The + is being unescaped as a space by the HTTP server.
You need to escape the + as %2B by calling CFURLCreateStringByAddingPercentEscapes
You need to urlencode the plus sign. It must become %2B for the receiver to think it's a plus sign.

How do I insert a POST request into a UIWebView

For a GET request I've tried this simple method:
NSString *urlAddress = #"http://example.com/";
NSURL *url = [NSURL URLWithString:urlAddress];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[uiWebViewThingy loadRequest:request];
(Although it doesn't seem to work if the request contains high UTF-8 characters. )
I want to send a POST from the iPhone.
This also give an overview for sending POST/GET requests although what I really want to do is embed the resulting web page into UIWebView. What would be the best way to go around that?
You can use an NSMutableURLRequest, set the HTTP method to POST, and then load it into your UIWebView using -loadRequest.
Thanks for you answer Seva.
I've made a method out of your code, hope this helps other people :)
//-------------------------------------------------------------------
// UIWebViewWithPost
// init a UIWebview With some post parameters
//-------------------------------------------------------------------
- (void)UIWebViewWithPost:(UIWebView *)uiWebView url:(NSString *)url params:(NSMutableArray *)params
{
NSMutableString *s = [NSMutableString stringWithCapacity:0];
[s appendString: [NSString stringWithFormat:#"<html><body onload=\"document.forms[0].submit()\">"
"<form method=\"post\" action=\"%#\">", url]];
if([params count] % 2 == 1) { NSLog(#"UIWebViewWithPost error: params don't seem right"); return; }
for (int i=0; i < [params count] / 2; i++) {
[s appendString: [NSString stringWithFormat:#"<input type=\"hidden\" name=\"%#\" value=\"%#\" >\n", [params objectAtIndex:i*2], [params objectAtIndex:(i*2)+1]]];
}
[s appendString: #"</input></form></body></html>"];
//NSLog(#"%#", s);
[uiWebView loadHTMLString:s baseURL:nil];
}
to use it
NSMutableArray *webViewParams = [NSMutableArray arrayWithObjects:
#"paramName1", #"paramValue1",
#"paramName2", #"paramValue2",
#"paramName3", #"paramValue3",
nil];
[self UIWebViewWithPost:self.webView url:#"http://www.yourdomain.com" params:webViewParams];
(edited original answer to include newly tested code)
I just wanted to drop in my version of this request. I have used a dictionary to represent the post parameters.
It's a chunk of code but is simple enough to drop into a view with a webview and use for all URL loading. It will only POST if you send a "postDictionary". Otherwise it will use the url you sent it to just GET things.
- (void) loadWebView:(UIWebView *)theWebView withURLString:(NSString *)urlString andPostDictionaryOrNil:(NSDictionary *)postDictionary {
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringCacheData
timeoutInterval:60.0];
// DATA TO POST
if(postDictionary) {
NSString *postString = [self getFormDataString:postDictionary];
NSData *postData = [postString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
}
[theWebView loadRequest:request];
}
- (NSString *)getFormDataString:(NSDictionary*)dictionary {
if( ! dictionary) {
return nil;
}
NSArray* keys = [dictionary allKeys];
NSMutableString* resultString = [[NSMutableString alloc] init];
for (int i = 0; i < [keys count]; i++) {
NSString *key = [NSString stringWithFormat:#"%#", [keys objectAtIndex: i]];
NSString *value = [NSString stringWithFormat:#"%#", [dictionary valueForKey: [keys objectAtIndex: i]]];
NSString *encodedKey = [self escapeString:key];
NSString *encodedValue = [self escapeString:value];
NSString *kvPair = [NSString stringWithFormat:#"%#=%#", encodedKey, encodedValue];
if(i > 0) {
[resultString appendString:#"&"];
}
[resultString appendString:kvPair];
}
return resultString;
}
- (NSString *)escapeString:(NSString *)string {
if(string == nil || [string isEqualToString:#""]) {
return #"";
}
NSString *outString = [NSString stringWithString:string];
outString = [outString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// BUG IN stringByAddingPercentEscapesUsingEncoding
// WE NEED TO DO several OURSELVES
outString = [self replace:outString lookFor:#"&" replaceWith:#"%26"];
outString = [self replace:outString lookFor:#"?" replaceWith:#"%3F"];
outString = [self replace:outString lookFor:#"=" replaceWith:#"%3D"];
outString = [self replace:outString lookFor:#"+" replaceWith:#"%2B"];
outString = [self replace:outString lookFor:#";" replaceWith:#"%3B"];
return outString;
}
- (NSString *)replace:(NSString *)originalString lookFor:(NSString *)find replaceWith:(NSString *)replaceWith {
if ( ! originalString || ! find) {
return originalString;
}
if( ! replaceWith) {
replaceWith = #"";
}
NSMutableString *mstring = [NSMutableString stringWithString:originalString];
NSRange wholeShebang = NSMakeRange(0, [originalString length]);
[mstring replaceOccurrencesOfString: find
withString: replaceWith
options: 0
range: wholeShebang];
return [NSString stringWithString: mstring];
}
You can use something like ASIHTTPRequest to make the POST request (With the option of doing it asynchronously) and then load the response string/data into the UIWebView. Look at this page under the section titled Sending data with POST or PUT requests and then look at the Creating an asynchronous request section at the top for information on how to handle the response string/data.
Hope that helps, sorry if I misunderstood your question.
Using loadHTMLString, feed a page to the UIWebView that has a hidden, pre-populated form, then make that page do a Javascript forms[0].submit() on loading.
EDIT: First, you collect the input into variables. Then you compose HTML like this:
NSMutableString *s = [NSMutableString stringWithCapacity:0];
[s appendString: #"<html><body onload=\"document.forms[0].submit()\">"
"<form method=\"post\" action=\"http://someplace.com/\">"
"<input type=\"hidden\" name=\"param1\">"];
[s appendString: Param1Value]; //It's your variable
[s appendString: #"</input></form></body></html>"];
Then you add it to the WebView:
[myWebView loadHTMLString:s baseURL:nil];
It will make the WebView load the form, then immediately submit it, thus executing a POST request to someplace.com (your URL will vary). The result will appear in the WebView.
The specifics of the form are up to you...
Create POST URLRequest and use it to fill webView
NSURL *url = [NSURL URLWithString: #"http://your_url.com"];
NSString *body = [NSString stringWithFormat: #"arg1=%#&arg2=%#", #"val1",#"val2"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL: url];
[request setHTTPMethod: #"POST"];
[request setHTTPBody: [body dataUsingEncoding: NSUTF8StringEncoding]];
[webView loadRequest: request];
Here is a Swift version of Seva Alekseyev's answer which worked perfectly for me. Thanks for the nice post mate! BTW following code is in Swift 3.1.
func injectPOST(params data: [String: Any]) {
var str = String()
str.append("<html><head></head>")
str.append("<body onload=\"payment_form.submit()\">")
str.append("<form id=\"payment_form\" action=\"\(urlString)\" method=\"post\">") //urlString is your server api string!
for object in data { //Extracting the parameters for request
str.append("<input name=\"\(object.key)\" type=\"hidden\" value=\"\(object.value)\">")
}
str.append("</form></body></html>")
webView?.loadHTMLString(stringObj, baseURL: nil)
}