HTTP post w/ JSON to rails server from iOS - ios

I have succeeded in making a post using a HTTP Client by setting the content type as application/json and this json code:
{
"order": {
"name": "Tia Carter",
"location": "Corams",
"phone_number": "707",
"food": "Bobcat Burger"
}
}
The code works perfect and the order is registered in the database. I am trying to work this into my iOS app but keep getting syntax errors regarding the colons in the json. This is the objective-c code:
NSURL *nsURL = [[NSURL alloc] initWithString:#"http://0.0.0.0:3000/orders.json"];
NSMutableURLRequest *nsMutableURLRequest = [[NSMutableURLRequest alloc] initWithURL:nsURL];
// Set the request's content type to application/x-www-form-urlencoded
[nsMutableURLRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// Set HTTP method to POST
[nsMutableURLRequest setHTTPMethod:#"POST"];
// Set up the parameters to send.
NSString *paramDataString = [NSString stringWithFormat:#
"{ "order": {"%#:" ="%#","%#:"="%#","%#:"="%#","%#:"="%#"}}", #"name", _name.text, #"location", _location.text, #"phone_number", _phoneNumber.text, #"food", _order.text];
// Encode the parameters to default for NSMutableURLRequest.
NSData *paramData = [paramDataString dataUsingEncoding:NSUTF8StringEncoding];
// Set the NSMutableURLRequest body data.
[nsMutableURLRequest setHTTPBody: paramData];
// Create NSURLConnection and start the request.
NSURLConnection *nsUrlConnection=[[NSURLConnection alloc]initWithRequest:nsMutableURLRequest delegate:self];
I'd appreciate any ideas or guidance. Thanks.

I believe you have two problems:
You didn't escape quotas (put \ before all of them)
You don't need to put text "name", "location" and etc in parameters (it's not a problem per se, just a style thing)
Also, I would recommend to work with NSDictionary and convert it to JSON when you need to (it will save you a lot of nerves for unescaped quotas, missing bracket and so on).
Look this question how to convert NSDictionary to JSON:
Generate JSON string from NSDictionary in iOS

Related

Unable to add a header to NSMutableRequest

NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:tempURL]] autorelease];
[request setValue:encryptedValue forHTTPHeaderField:#"EncString"];
I could spot all other headers in the request but this specific header is missing, can any one let me know what could be the reasons.
I have tried the following code:
NSString *tempURL = #"https://stackoverflow.com/questions/50701101/unable-to-add-a-header-to-nsmutablerequest";
NSString *encryptedValue = #"whatever_that_has_no_special_characters_or_values_that_would_make_you_think_it_is_relevant_to_reproduce_this_issue";
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:tempURL]];
[request setValue:encryptedValue forHTTPHeaderField:#"EncString"];
NSLog(#"%#", request.allHTTPHeaderFields);
The output is:
{
EncString = "whatever_that_has_no_special_characters_or_values_that_would_make_you_think_it_is_relevant_to_reproduce_this_issue";
}
which looks good. There is no reason to suspect the code you provided is responsible for the issue. Maybe you should check one of the following:
Is encryptedValue truly a valid object to be placed into header (is string, not too long, no very special characters)
Is the object you are printing really this specific request (printing NSLog(#"%p", request); returns same result)
In no place in this object a herder is being removed (if nothing else subclass NSMutableURLRequest and override relevant methods to track what is going on)
If none of these work create a post with additional details on what you have done, where are you checking these headers and "could spot all other headers".

Does an iOS http 'get' have a URL length limit

I'm trying to do a simple get in iOS (Objective C) using a simulator and not a real device.
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:theGetURL]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
[newRequest setHTTPMethod: #"GET"];
NSError *requestError2;
NSURLResponse *urlResponse2;
NSData *response2 = [NSURLConnection sendSynchronousRequest:newRequest returningResponse:&urlResponse2 error:&requestError2];
NSString* secondResponse = [[NSString alloc] initWithData:response2 encoding:NSUTF8StringEncoding];
NSLog(#"error = %#",requestError.localizedDescription);
NSLog(#"response=%#",secondResponse);
NSLog(#"url response = %#",urlResponse);
This code works perfectly when I'm passing a simple url. When I try the code with a longer (around 4000 characters) url, the code doesn't work (no error is printed).
I am aware that a post is better for this kind of thing, but my question is, is this expected from a get request?
Also, my url works perfectly in my mac and iOS browsers.
As you suspect, I think you need to consider moving to use POST rather then GET. The server side limit is 8K, however it seems this can be much less for the client side.
The following discussion sums everything up well. It also seems to imply the limit for Safari is 2K, which probably means it is the same or less for iOS, which would explain your problem with 4000 characters.
maximum length of HTTP GET request?
I think your URL query parameter might have any character that is not encoded. Try to ensure it.
For encoding you may try this code
- (NSString *)encodeQueryParameter:(NSString *)str
{
CFStringRef ref = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
(__bridge CFStringRef)str,
NULL,
CFSTR(":/=,!$&'()*+;[]##?"),
kCFStringEncodingUTF8);
NSString *result = (__bridge_transfer NSString *)ref;
return result;
}

How to send the character "&" via HTTP POST to server with iOS 7?

I want to send some data via http post from my App to the server. All symbols can be accepted by the server, except the &.
the server is php;
content-type is application/x-www-form-urlencoded, and charset is utf-8.
Encoding is NSUTF8StringEncoding.
I tried also changing the & with URLEncoding, i.e. & --> %26. the server can receive it, but cannot display it recht. It's shown in %26, not &.
But, the server can properly received and displayed, if it is sent by android or web side.
The code is the following:
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"xxx.com/server.php"]];
postRequest.HTTPMethod = #"POST";
[postRequest setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
NSString *bodyString = [NSString stringWithFormat:#"data=&&&&"];
postBody = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
NSURLConnection *postConnect = [[NSURLConnection alloc]initWithRequest:postRequest delegate:self];
hope this helps you
NSString *encodedString = [myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
It won't replace your string inline; it'll return a new string. That's implied by the fact that the method starts with the word "string". It's a convenience method to instantiate a new instance of NSString based on the current NSString.
Note--that new string will be autorelease'd, so don't call release on it when you're done with it.
It should be with the function
(NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)url, NULL, (CFStringRef)#"&", kCFStringEncodingUTF8))

How do I set up and implement HTTP method for authorization?

I'm trying to get into a webAPI my classmate created with my iphone APP I've created. Right now, it connects, but my app just crashes because it tells me that I need authorization. So if for example, the username is abc and password abc123, How would I implement the HTTP method specifically to get passed authorization??
NSString *geturl = #"http://192.168.1.96:50364/api/transaction" ;
setValue:(NSString*)" " forHTTPHeaderField:(NSString*)username;
getjson *mds=[[getjson alloc] init];
SEL selector = #selector(addData:);
[mds setDirectionsQuery:geturl
withSelector:selector
withDelegate:self];
Edit: if the above problem is too confusing, what is the basic syntax/code for setting up the value and the key for username and password? I am sure
setValue:(NSString*)"abc " forHTTPHeaderField:(NSString*)username;
setValue:(NSString*)"abc123 " forHTTPHeaderField:(NSString*)password;
is not correct. compiler is not letting me run the program.
Your strings are missing #
Try setValue:(NSString*)#"abc " forHTTPHeaderField:(NSString*)username; although if the code you pasted is complete, it doesn't say what your setting values to.
I personally use NSMutableRequest and create the request and authorisation like this. Note that the auth gets Base64 encoded:
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:_urlString]];
NSString *basicAuthCredentials = [NSString stringWithFormat:#"%#:%#", username, password;
NSString *authValue = [NSString stringWithFormat:#"Basic %#", AFBase64EncodedStringFromString(basicAuthCredentials)];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization"];

iOS - POSTing file upload requests to Copy.com

Working with the new Copy.com API. Successfully signed in with OAuth1 and have made requests for profile data, and can successfully create folders.
If you look at the API docs here: https://www.copy.com/developer/documentation#api-calls/filesystem and go to the section on making POST requests to the API to create new files, the instructions for the headers are a little strange to me. See here:
Content-Type:multipart/form-data; boundary=----WebKitFormBoundary5dcD4Bk7SevSsaMg
Content-Disposition: form-data; name="X-Api-Version"
1.0
------WebKitFormBoundary5dcD4Bk7SevSsaMg
Content-Disposition: form-data; name="file"; filename="animation.gif"
Content-Type: image/gif
<BASE64 ENCODED FILE STRUCTURE>
------WebKitFormBoundary5dcD4Bk7SevSsaMg--
As you can see, there are multiple header fields for Content-Type and Content-Disposition, separated by the boundary parameter. When using NSMutableURLRequest and -setValue:forHTTPHeaderField I just overwrite previous values. Here's what I have for my header fields:
NSString *boundaryString = #"----WebKitFormBoundary5dcD4Bk7SevSsaMg";
NSString *disposition = #"Content-Disposition: form-data; name=\"ThankYou.mp3\" filename=\"ThankYou.mp3\"";
NSString *type = #"Content-Type: audio/mp3";
NSData *dispositionData = [disposition dataUsingEncoding:NSUTF8StringEncoding];
NSData *typeData = [type dataUsingEncoding:NSUTF8StringEncoding];
NSData *boundaryData = [boundaryString dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *songData = [NSMutableData data];
[songData appendData:boundaryData];
[songData appendData:dispositionData];
[songData appendData:typeData];
[songData appendData:mp3Data]; //initiated before. From my mainBundle.
[songData appendData:boundaryData];
[request setHTTPBody:songData];
[self.myAuth authorizeRequest:request];
[request setValue:#"1" forHTTPHeaderField:#"X-Api-Version"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"multipart/form-data; boundary=----WebKitFormBoundary5dcD4Bk7SevSsaMg" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"form-data; name=\"X-Api-Version\"=1.0" forHTTPHeaderField:#"Content-Disposition"];
As you can see, I tried to replicate the structure of the POST request by appending a boundary, Content-Disposition and Content-Type in front of the actual Body Data, and then append a boundary at the end.
At the end of this I am only created a folder called "ThankYou.mp3" on Copy.com, which is what happens when you make a POST request with empty body data. I assure you the body data is not empty :-)
Can anyone help me out here?
The code used in this class is tested to work: COCopyClient.m
It might be easier to just use the library: copy-mac-ios-sdk

Resources