Been using AFNetworking 2.0 for the past two projects for a medium sized project to great success.
This one call though, to post a user' login info, keep failing on me (server states incorrect login & password, login is the email, we've check on the server and the values are the same I'm trying to send)
The server developer does not handle iOS / ObjC (java / mongoDB guy), All I'm giving is a URL and the parameters I need to pass with Content-Type = application/x-www-form-url-encoded
I read somewhere that characters such as # (in the email) could cause problems
Could anyone with more experience than me here chip in? my operation creation method is below, any help is TRULY appreciated.
-(AFHTTPRequestOperation *)loginUserWithParameters:(NSDictionary *)loginParameters
{
/*
parameters dictionary:
email
psw
deviceToken
*/
NSString *url=SERVER_USER_LOGIN;
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:url]];
// [httpClient setParameterEncoding:AFFormURLParameterEncoding];
NSMutableURLRequest *request=[httpClient requestWithMethod:#"POST" path:nil parameters:nil];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:loginParameters options:kNilOptions error:nil];
[request setHTTPBody:jsonData];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[AFNetworkActivityIndicatorManager sharedManager].enabled=YES;
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
return operation;
}
Actually you say with your code that you will send url-encoded data to your server, but you are overriding the postBody of your request with custom data. So you should create your request with:
NSMutableURLRequest *request=[httpClient requestWithMethod:#"POST" path:nil parameters:loginParameters];
And you should delete below lines:
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:loginParameters options:kNilOptions error:nil];
[request setHTTPBody:jsonData];
I think above changes will be enough.
Related
So, I have to methods to approach a web service:
A GET:
- (NSDictionary *)getDataFromURL:(NSString*)url {
NSString * serverAddress =[NSString stringWithFormat:url,mySchoolURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL
URLWithString:serverAddress]
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10
];
[request setHTTPMethod: #"GET"];
NSError *requestError = nil;
NSURLResponse *urlResponse = nil;
NSData *response = [NSURLConnection
sendSynchronousRequest:request
returningResponse:&urlResponse
error:&requestError];
NSError* error = nil;
NSDictionary *output = [NSJSONSerialization JSONObjectWithData:response options:kNilOptions error:nil];
return output;
}
and a POST:
-(NSData*)postData:(NSDictionary*)requestData toUrl:(NSString*)destination {
NSError *error;
NSData *postdata = [NSJSONSerialization dataWithJSONObject:requestData options:0 error:&error];
NSString *postLength = [NSString stringWithFormat:#"%lu",(unsigned long)[postdata length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:destination,mySchoolURL]]];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postdata];
[request setHTTPMethod:#"POST"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
return nil;
}
Somehow, the HTTP header of the POST method does include the cookie's SessionID, while the GET one doesn't.
I have to admit that I don't fully understand the innards of cookies and the like, but several sources on the web claim that I should't worry about the cookies at all, since they are taken care of automatically.
Anyway, the web service I'm talking to expects a Session ID in both POST and GET situations, so now I'm forced to start understanding what's going on.
Could any of you help me out here?
The concrete question is: how to I pass a Session_ID to a URL using a GET method?
Thanks ahead
Okay so one way to do this is by simply adding the cookies to the HTTP headers. When doing this the correctness of the URL is key. If the protocol is wrong, some cookies may not be included. You will need to get all available cookies, and then create a dictionary for the headers with he available cookies. Then you simply add those headers to your request by calling setAllHTTPHeaderFields:. I placed a quick example of how to do this below, however you can learn more about how cookies work at the Apple Documentation Class Reference
NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookiesForURL:request.URL];
NSDictionary *headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
[request setAllHTTPHeaderFields:headers];
I really hope this helps you out. I would recommend reading the Apples Documentation to help you out as much as possible. I wish you the best of luck!
Good day,
I am trying to use a Codeigniter based API to connect with iOS and using NSURLRequest.
The API is in debugMode and for now it returns the same key value pair as json as the one that you are posting. I have tried posting the values to the link through postman and it works correctly, however when I post it through my iOS application, the json response is received but the array that should contain the post values is empty.
Here is the iOS Code snippet :
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",BASEURL,service]];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSString * params = #"authkey=waris";
NSData * postData = [params dataUsingEncoding:NSUTF8StringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu",(unsigned long)[postData length]];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];;
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
NSLog(#"Posting : '%#' to %#",params,url);
[connection start];
This is the response when I post the same parameters through postman ( A RESTFUL Client for Chrome )
{
"status": "1",
"data": {
"authkey": "warisali"
}
}
However when I query the same API from the above iOS Code I am getting this :
{
data = 0;
status = 1;
}
Any help on the matter will be highly appreciated!
I had same issue (not with CodeIgniter but with Ruby ...)
Try something like this, solved my problem.
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",BASEURL,service]];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSDictionary *paramDict = #{#"authkey": #"waris"};
NSError *error = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:paramDict options:NSJSONWritingPrettyPrinted error:&error];
if (error)
{
NSLog(#"error while creating data %#", error);
return;
}
NSString *postLength = [NSString stringWithFormat:#"%lu",(unsigned long)[postData length]];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];;
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
NSLog(#"Posting : '%#' to %#",params,url);
[connection start];
I ended up using the ASIHttpRequest + SBJson combo and that worked like Charm!
After adding the ASIHttpRequest core classes and SBJson Classes to parse the JSON, I was able to achieve what I wanted !
The problem is that because of the way you're creating the connection, it will start immediately, before you've finished configuring the request. Thus, you're creating a mutable request, creating and starting the connection, then attempting to modify the request and then trying to start the request a second time.
You can fix that by changing the line that says:
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
To say:
NSURLConnection *connection=[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
Or, easier, just move the original instantiation of the NSURLConnection (without the startImmediately:NO) after you've finished configuring your request, and then eliminate the [connection start] line altogether.
I have a problem:
I need to make a post to a php using json, but it responds only with the data type x-www-form-urlencoded, I used the postman of google chrome and not form-data is done, I used this way but tells me that the parameters are incorrect, I need help:
NSString *jsonRequest = [NSString stringWithFormat:#"j_username=%#&j_password=%#",nombre,pass];
NSURL *url = [NSURL URLWithString:urlhttp];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody: requestData];
[NSURLConnection connectionWithRequest:request delegate:self];
For starters:
Your string has nothing to do with JSON. It's just a plain string
Your username & password must be URL encoded
[NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]] is wrong. You would have to use [NSData dataWithBytes:[jsonRequest UTF8String] length:[[jsonRequest UTF8String] length]]
Where's JSON in your example? You have nothing looking like it in the example.
You're doing a few things wrong in setting up the request, check Sulthan answer.
My advice is to use a library that handles such minor formal details - like encoding and headers - for you.
With AFNetworking you could write something like.
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://whatever.com/"]];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[httpClient setParameterEncoding:AFFormURLParameterEncoding]
NSDictionary * params = #{
#"j_username": nombre,
#"j_password": pass
};
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:#"relative/path/to/resource"
parameters:params];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response: %#", [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
[httpClient enqueueHTTPRequestOperation:operation];
(example based on http://samwize.com/2012/10/25/simple-get-post-afnetworking/)
While in terms on LOC in may look not so great, consider that:
httpClient is initialized just once and you can reuse it for subsequent requests, centralizing the configuration
parameters gets automatically encoded in the desired format and if you have to change the encoding in the future you just have to change AFFormURLParameterEncoding to something else.
you get a nice block-based API instead of relying on the cumbersome NSURLConnectionDelegate methods
I'm sure I'm dense from being new to iOS programming, but, I am having problems with AFNetworking. Specifically, when I use it, nothing happens. I don't get any response from the server, but, I also don't get any errors. All of the properties end up NULL.
Here is my request:
NSMutableDictionary *requestArray = [NSMutableDictionary new];
[requestArray setObject: #"getBio"
forKey: #"action"];
[requestArray setObject: #"1"
forKey: #"bioID"];
NSError * error = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:requestArray options:0 error:&error];
NSString *myRequestString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSMutableURLRequest *request = [ [ NSMutableURLRequest alloc ] initWithURL: [ NSURL URLWithString: #"http://localhost/LP/JSON/Secure/bio.php" ] ];
[ request setHTTPMethod: #"POST" ];
[ request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"content-type"];
[ request setHTTPBody: [myRequestString dataUsingEncoding:NSUTF8StringEncoding]];
This seems to work as I get my expected result if I simply pass the request into a UIWebView or if I use this:
NSURLResponse *response;
NSError *err;
NSData *returnData = [ NSURLConnection sendSynchronousRequest: request returningResponse:&response error:&err];
NSString *content = [NSString stringWithUTF8String:[returnData bytes]];
NSLog(#"responseData: %#", content);
In other words, the POST is successful and JSON is returned.
But, none of these do anything (no error, no response):
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(#"Data: %# %#", [JSON valueForKeyPath:#"firstName"], [JSON valueForKeyPath:#"lastName"]);
} failure:nil];
Nor does even the bare bones attempt work:
AFURLConnectionOperation *operation = [[AFURLConnectionOperation alloc] initWithRequest:request];
Obviously, I'm doing something horribly wrong. But, the silent failures are making this hard to figure out.
Thanks for any help.
EDIT:
Nevermind.. I am dense.
Wasn't creating the NSOperationQueue.
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
Although, I'm still unclear why the properties aren't getting set. But, it looks like I at least have data.
Creating the request operation object does not automatically kick off the request. Like you pointed out in your edit, it's up to you to either enqueue it into an NSOperationQueue or do [operation start] manually.
I would recommend that you communicate with your server using AFHTTPClient, since that provides a built-in mechanism to correctly set either your query string or HTTP body based on parameters you pass in. See the Gowalla API example client in the sample code, and the method AFHTTPClient -postPath:parameters:success:failure.
I am trying to achieve the following in Objective-C:
curl -X POST -u "<application key>:<master secret>" \
-H "Content-Type: application/json" \
--data '{"aps": {"badge": 1, "alert": "The quick brown fox jumps over the lazy dog."}, "aliases": ["12345"]}' \
https://go.urbanairship.com/api/push/
Is there some sort of library I can use that achieves this? Obviously I have all of the values ready to go ahead and make my request, but I'm not exactly sure how to do it in Objective-C.
I am using TouchJSON, however I'm not quite sure how to construct the correct JSON payload above and POST this to the server (also I'd prefer this to be an asynchronous request rather than a synchronous).
NSError *theError = NULL;
NSArray *keys = [NSArray arrayWithObjects:#"aps", #"badge", #"alert", #"aliases", nil];
NSArray *objects = [NSArray arrayWithObjects:?, ?, ?, ?, nil];
NSDictionary *theRequestDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSURL *theURL = [NSURL URLWithString:#"https://go.urbanairship.com/api/push/"];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:theURL cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:10.0f];
[theRequest setHTTPMethod:#"POST"];
[theRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSData *theBodyData = [[CJSONSerializer serializer] serializeDictionary:theRequestDictionary error:&theError];
[theRequest setHTTPBody:theBodyData];
NSURLResponse *theResponse = NULL;
NSData *theResponseData = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&theResponse error:&theError];
NSDictionary *theResponseDictionary = [[CJSONDeserializer deserializer] deserialize:theResponseData error:&theError];
NSURL *url = [NSURL URLWithString:#"https://go.urbanairship.com/api/push/"];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
[req setHTTPMethod:#"POST"];
//... set everything else
NSData *res = [NSURLConnection sendSynchronousRequest:req returningResponse:NULL error:NULL];
or send asynchronous request with
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:some];
have a look at NSMutableURLRequest Class Reference to see how to set what.
You can use NSURLConnection for this; here's a sample:
How do I make HTTP post request for getting JSON object in response for iPhone application?
There may be a way to actually run a curl script proper, using NSTask: http://borkware.com/quickies/one?topic=nstask
I searched a lot to convert this cUrl request to send Urban Airship push notifications, I finally did it below is the source code which worked for me:
Required:
ASIHTTPRequest //Required to execute Http request
+(void)sendUrbanAirshipPushWithPayload:(NSString *) payload
{
//payload = #"{"aps": {"badge": 1, "alert": "The quick brown fox jumps over the lazy dog."}, "aliases": ["12345"]}";
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:#"https://go.urbanairship.com/api/push/"]];
[request addRequestHeader:#"Content-Type" value:#"application/json"];
[request setRequestMethod:#"POST"];
//Set the HTTP Basic Authentication header with the application key as the username, and the master secret for the password
[request setUsername:kUrbanAirshipKey];
[request setPassword:kUrbanAirshipMasterSecret];
[request setPostBody:[NSMutableData dataWithData:[payload dataUsingEncoding:NSUTF8StringEncoding]]];
[request startSynchronous];
if([request error])
{
NSLog(#"Code : %d, Error: %#",[[request error] code],[[request error] description]);
}
NSLog(#"Code: %d, Description: %#, Message: %#",[request responseStatusCode],[request responseData],[request responseStatusMessage]);
}