I don't know whether I missed something obvious or not but what should appear correct is not working. Maybe I need a pair of fresh eyes ?
I am testing Today Extension (widget) for one of my app and in this widget, I am trying to make a request to Google Directions API.
My normal app itself has no problem making and receiving the request but the widget itself is not playing right.
In my normal app, I'm using AFNetworking but AFNetworking has some problems with [UIApplication sharedApplication] not being accessible inside a widget, so I am resorting to using NSURLSession to make my POST request:
NSError *error;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSString *directionsURL = [#"https://maps.googleapis.com/maps/api/" stringByAppendingString:#"directions/json"];
NSURL *url = [NSURL URLWithString:directionsURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPMethod:#"POST"];
// ------------------------------------------------------------------
// setup params
// ------------------------------------------------------------------
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
NSString *strOrigin = [[NSString alloc] initWithFormat:#"%lf,%lf", fromLocation.latitude, fromLocation.longitude];
NSString *strDestination = [[NSString alloc] initWithFormat:#"%lf,%lf", toLocation.latitude, toLocation.longitude];
[params setValue:strOrigin forKey:#"origin"];
[params setValue:strDestination forKey:#"destination"];
[params setValue:#"transit" forKey:#"mode"];
[params setValue:#"true" forKey:#"alternatives"];
NSString *GoogleAPIBrowserKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"GoogleAPIBrowserKey"];
[params setValue:GoogleAPIBrowserKey forKey:#"key"];
[params setValue:#"fewer_transfers" forKey:#"transit_routing_preference"];
DLog(#"widget params = %#", params);
NSData *postData = [NSJSONSerialization dataWithJSONObject:params options:0 error:&error];
if(error)
{
DLog(#"error setting up PostData: %#", error.localizedDescription);
}
[request addValue:[NSString stringWithFormat:#"%d", postData.length] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error)
{
DLog(#"Widget Error requesting route: %#", error.localizedDescription);
}
else
{
NSError *jsonError = nil;
NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if(error)
{
DLog(#"Error converting widget response data: %#", error.localizedDescription);
}
DLog(#"Widget Google Response = %#", responseDict);
}
}];
[postDataTask resume];
My Xcode console outputs the following:
widget params = {
alternatives = true;
destination = "-31.834382,115.804225";
key = **********************;
mode = transit;
origin = "-31.833961,115.806565";
"transit_routing_preference" = "fewer_transfers";
}
Widget Google Response =
{
"error_message" = "Invalid request. Missing the 'origin' parameter.";
routes = (
);
status = "REQUEST_DENIED";
}
Which leads me to believe the HTTP Body of my request is lost somehow during the network request operation. How can 'origin' be missing when the log shows it as part of my params dictionary ?
I've tried po data to see if the data variable was nil but it was not nil.
I'm scratching my head over this one. If anyone can see where I've gone wrong and point it out to me, I'll be one happy chap.
Why do I always do this to myself ?
Short Answer
Use GET Request lad, not POST.
Long Answer
Went for a walk, came back home, 1 hour later. Problem solved.
Upon looking at my normal app version of my code that uses AFNetworking, I realised my noobness mistake.
I was using POST request in my Today Extension when I should be using GET request like how I was doing it in my AFNetworking code.
For that reason, the new params needs to be URL encoded instead of being part of HTTP Body, so new code is now:
NSError *error;
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
// ------------------------------------------------------------------
// setup URL params
// ------------------------------------------------------------------
NSMutableString *urlParams = [[NSMutableString alloc] initWithString:#"?"];
NSString *strOrigin = [[NSString alloc] initWithFormat:#"%lf,%lf", fromLocation.latitude, fromLocation.longitude];
NSString *strDestination = [[NSString alloc] initWithFormat:#"%lf,%lf", toLocation.latitude, toLocation.longitude];
NSString *GoogleAPIBrowserKey = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"GoogleAPIBrowserKey"];
[urlParams appendFormat:#"origin=%#&destination=%#&mode=transit&alternatives=true&key=%#&transit_routing_preference=fewer_transfers", strOrigin, strDestination, GoogleAPIBrowserKey];
NSString *directionsURL = [[NSString alloc] initWithFormat:#"https://maps.googleapis.com/maps/api/%#%#", #"directions/json", urlParams];
NSURL *url = [NSURL URLWithString:directionsURL];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
[request setHTTPMethod:#"GET"];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error)
{
DLog(#"Widget Error requesting route: %#", error.localizedDescription);
}
else
{
NSError *jsonError = nil;
NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&jsonError];
if(jsonError)
{
DLog(#"Error converting widget response data: %#", error.localizedDescription);
}
DLog(#"Widget Google Response = %#", responseDict);
}
}];
[dataTask resume];
Terribad. I'm sorry, I've been staring at the screen for hours today :D
Related
I want to add my token in Authorization header
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSLog(#"%# urlis ====>",urlString);
NSData *data = [NSData dataWithContentsOfURL:url2];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData *dataaa = [ret dataUsingEncoding:NSUTF8StringEncoding];
id json = [NSJSONSerialization JSONObjectWithData:dataaa options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
You can use NSMutableRequest -
NSURL *url2 = #"http://54.149.31.77:3000/api/search?number=98745612661";
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url2];
[request setHTTPMethod:#"GET"];
[request setValue:[[NSUserDefaults standardUserDefaults] valueForKey:#"token"] forHTTPHeaderField:#"Authorization"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
// add any additional headers or parameters
NSURLSessionDataTask *downloadTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
// do your response handling
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray * resultDict =[json objectForKey:#"name"];
}
}];
[downloadTask resume];
To understand in more detail about NSURLSession refer to this Tutorial
NSMutableURLRequest* request = [[NSMutableURLRequest alloc] initWithURL:url];
[request addValue:VALUE forHTTPHeaderField:#"Authorization"];
Try to create a Mutable request and add your authorization header to it. You can send this request as a parameter to any one. Either to AFNetworking (or some third party network) library API calls or to URLSession (by Apple)
For more info on NSMutableRequest
You can pass it by
[request setValue:#"Your Token" forHTTPHeaderField:#"Authorization"];
Edited :
As per your comment if you want to change your response then your should use NSMutableDictionary instead of NSArray like.
Note: Your response should Dictionary if it will array then use NSMutableArray
NSMutableDictionary * resultDict =[json objectForKey:#"name"];
[resultDict setObject:#"Your Token" forKey:#"Authorization"];
hello all i know this kind of question asked previously but i didn't get any solution from them
in my project i am working in login view when i am put code on login button i am getting an error
Error : Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL"
UserInfo=0x7fb37b62c9a0 {NSLocalizedDescription=unsupported URL,
NSUnderlyingError=0x7fb37b715a20 "The operation couldn’t be completed.
(kCFErrorDomainCFNetwork error -1002.)"}
but i am using the same code for login which i used in my previous projects and it works fine there
here is my code:
-(IBAction)login:(id)sender
{
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:#"http://eyeforweb.info.bh-in-15.webhostbox.net/myconnect/api.php?token={LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUc4d0RRWUpLb1pJaHZjTkFRRUJCUUFEWGdBd1d3SlVBeWo0WE9JNjI4cnJRTG9YeEpXNG1zUWI1YmtvYk1hVQpzMnY1WjFKeXJDRWdpOVhoRzZlZk4rYTR0eGlMTVdaRXdNaS9uS1cyL1NCS2pCUnBYUzVGYUdiV0VLRG1WOXkvCkYrWHhsUXVoeER0MEV3YkRBZ01CQUFFPQotLS0tLUVORCBQVUJMSUMgS0VZLS0tLS0K}&method=user.getLogin"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"*/*" forHTTPHeaderField:#"Accept"];
[request setHTTPMethod:#"POST"];
NSString *mapData = [NSString stringWithFormat:#"login=abc#gmail.com&password=123456"];//,username.text, password.text];
NSData *postData = [mapData dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
[request setHTTPBody:postData];
NSLog(#"map data is = %#",mapData);
NSURLSessionDataTask * postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * data, NSURLResponse* response, NSError * error) {
if(error == nil)
{
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSString *text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(#"Data = %#",text);
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"jsondic= %#",jsonDic);
NSDictionary *userDataDic = [jsonDic objectForKey:#"data"];
NSLog(#"Dict is %#",userDataDic);
Please help me to resolve it i already see the similar type of questions but didn't overcome from this issue
Any help is appreciated
I tried your code.Except your url the other lines of code is correct.If you pass your corrct URL,it works perfectly.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"http://eyeforweb.info.bh-in-15.webhostbox.net/myconnect/api.php"]]; //pass your url here
[request setHTTPMethod:#"POST"];
//Passing The String to server
NSString *strUserId = #"pradeep.kumar#eyeforweb.com";
NSString *strPassword = #"admin123";
NSString *userUpdate =[NSString stringWithFormat:#"login=%#&password=%#",strUserId,strPassword, nil];
//Check The Value what we passed
NSLog(#"the data Details is %#", userUpdate);
//Convert the String to Data
NSData *data1 = [userUpdate dataUsingEncoding:NSUTF8StringEncoding];
NSLog(#"The postData is - %#",data1);
//Apply the data to the body
[request setHTTPBody:data1];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if(httpResponse.statusCode == 200)
{
NSError *parseError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(#"The response is - %#",responseDictionary);
NSInteger success = [[responseDictionary objectForKey:#"success"] integerValue];
if(success == 1)
{
NSLog(#"Login SUCCESS");
}
else
{
NSLog(#"Login FAILURE");
}
}
else
{
NSLog(#"Error");
}
}];
[dataTask resume];
I'm trying to post new data to a ws but im geting error each time
I need to
1-pass a username and password each time
2-code the data with AES256 WITH THE API KEY
Code:
- (IBAction)AddTicket:(id)sender {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *URL = [[NSURL alloc] initWithString:#"http://dev.enano-tech.com/api/Ticket"];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:#"1",#"id",#"1",#"idProject",#"1",#"idTicketType",#"nameo",#"name",#"nameo",#"description", #"1",#"idStatus",#"2016-06-23 15:20:49",#"creationDateTime", nil];
NSData *dataToPost = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
NSData *final =[dataToPost AES256EncryptWithKey:#"02b6e206868660a0d59d2e51a11fdcd6"];
//
NSLog(#"postData1e == %#",final);
NSLog(#"final %#",dataToPost);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request setHTTPMethod:#"POST"];
[request addValue:#"CURLAUTH_BASIC" forHTTPHeaderField:#"CURLOPT_HTTPAUTH"];
[request addValue:#"Basic YWRtaW46YWRtaW5hZG1pbg==" forHTTPHeaderField:#"authorization"];
[request addValue:#"admin:adminadmin" forHTTPHeaderField:#"CURLOPT_USERPWD"];
[request addValue:#"true" forHTTPHeaderField:#"CURLOPT_RETURNTRANSFER"];
[request addValue:#"false" forHTTPHeaderField:#"CURLOPT_SSL_VERIFYPEER"];
[request addValue:#"POST" forHTTPHeaderField:#"CURLOPT_CUSTOMREQUES"];
[request addValue:#"true" forHTTPHeaderField:#"CURLOPT_POST"];
[request addValue:#"false" forHTTPHeaderField:#"CURLOPT_POSTFIELDS"];
[request setHTTPBody:final];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSString *str = [[NSString alloc]initWithData:final encoding:NSUTF8StringEncoding];
NSLog(#"data %#",data);
NSLog(#"respoce %#",response);
NSLog(#"result == %#",result);
}];
[postDataTask resume];
}
Response:
2016-08-02 15:06:47.768 Projector[3936:1619429] result == {"error":"invalid API query", "message":"'data' is not correctly encoded for method POST. Request for correct API KEY"}
this is the documentation of api:
enter image description here
Your webserver is missing "data" from the website. To fix it, you'll need to add that field to your form or find the correct field name (case sensitive)
To my understanding, to use this website I have to convert an image to a base64 encoded image and then send it to this website. The website will then send me back a number (as a decimal).
https://docs.indico.io/docs/rest-api-image-analysis
I've tried using a number of steps, namely trying to alter a similar process used for sending text and receiving a number. Any tips?
UPDATE:
- (IBAction)press:(id)sender {
//UIImage *imager = photos.image;
NSData *imageData = UIImageJPEGRepresentation(photos.image, 1.0);
NSString *base64Img = [imageData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
//not sure if #"data" or #"data.json" and whether the base64img should be behind it
NSDictionary *parameters = #{#"data":base64Img};
NSMutableString *parameterString = [NSMutableString string];
for (NSString *key in [parameters allKeys]) {
if ([parameterString length]) {
[parameterString appendString:#"&"];
}
[parameterString appendFormat:#"%#=%#", key, parameters[key]];
NSURL *url = [NSURL URLWithString:#"http://apiv2.indico.io/contentfiltering?key='17767cb46eb4b4f568832be2c953022b"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[parameterString dataUsingEncoding:NSUTF8StringEncoding]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (!error) {
if ([data length]) {
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
//GET RESULT;
NSLog(#"A %#", parameters[#"results"]);
}
} else {
NSLog(#"%#", error);
}
}];
[task resume];
}
the results I get usually return as (null)
maybe try going
NSDictionary *parameters = #{#"data":base64Img};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters
options:nil
error:&error];
//do some error checking
NSURL *url = [NSURL URLWithString:#"http://apiv2.indico.io/contentfiltering?key='17767cb46eb4b4f568832be2c953022b"];
NSURLSession *session = [NSURLSession sharedSession];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:jsonData];
//...
just doing this off the top of my head so may need some tweaking
If I had to guess it looks like you've accidentally added a typo to your API key. In the line above:
http://apiv2.indico.io/contentfiltering?key='17767cb46eb4b4f568832be2c953022b
should instead read:
http://apiv2.indico.io/contentfiltering?key=17767cb46eb4b4f568832be2c953022b
Since URL parameters are sometimes quoted and I'm not extremely familiar with objective-c's internal request handling I would guess that that is leading to the strange behavior you're seeing.
I tried to add an entry to db using a POST request in Objectve-C. My service is:
#RequestMapping(method = RequestMethod.POST, headers = "content-type=application/json")
public
#ResponseBody
boolean addEmployee(#ModelAttribute User user) {
try {
logger.log(Level.INFO, user.getCountry());
userDataService.addUser(user);
return true;
//return new Status(1, "Employee added Successfully !");
} catch (Exception e) {
e.printStackTrace();
return false;//new Status(0, e.toString());
}
}
When I try this on Postman, it's working fine with x-www-form-urlencoded. But when I try this in Objective-C, nothing happens. Here is what I tried:
NSString *jsonInputString = #"{\"userName\":\"abcd\"}";
NSString *jsonRequest = jsonInputString;
NSLog(#"jsonRequest is %#", jsonRequest);
NSURL *url = [NSURL URLWithString:#"http://localhost:8080/user"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSMutableURLRequest *rq = [NSMutableURLRequest requestWithURL:url];
[rq setHTTPMethod:#"POST"];
NSData *jsonData = [jsonInputString dataUsingEncoding:NSUTF8StringEncoding];
[rq setHTTPBody:jsonData];
[rq setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[rq setValue:[NSString stringWithFormat:#"%ld", (long)[jsonData length]] forHTTPHeaderField:#"Content-Length"];
[NSURLConnection sendAsynchronousRequest:rq queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
NSLog(#"%#", [error localizedDescription]);
}];
In completion block, the log prints "Could not connect to the server". How can I call the service with JSON data?
Something like this should work
// 1: Create your URL, Session config and Session
NSString *jsonInputString = #"{\"userName\":\"abcd\"}";
NSString *jsonRequest = jsonInputString;
NSURL *url = [NSURL URLWithString:#"http://localhost:8080/user"];
NSURLSessionConfiguration *config =
[NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
// 2: Create NSMutableRequest object
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
request.HTTPMethod = #"POST";
// 3: Create Jsondata object
NSError *error = nil;
NSData *jsonData = [jsonInputString dataUsingEncoding:NSUTF8StringEncoding];
// Asynchronously Api is hit here
NSURLSessionUploadTask *dataTask =
[session uploadTaskWithRequest:request
fromData:data
completionHandler:^(NSData *data, NSURLResponse *response,
NSError *error) {
NSLog(#"%#", data);
NSDictionary *json =
[NSJSONSerialization JSONObjectWithData:data
options:0
error:nil];
NSLog(#"%#", json);
success(json);
}];
[dataTask resume]; // Executed First