NSMutableURLRequest Unsupported URL - ios

I'm using the Open Weather Map API to fetch the user's current weather.
When I run the request in Postman, I get a status code 200 and am able to receive data. However, in Xcode I get the error -1002
Here is the code executing the 'GET' request:
// Configure URL String
NSString *apiKey = #"MY_API_KEY";
NSString *urlString = [[NSString alloc] initWithFormat:#"api.openweathermap.org/data/2.5/weather?APPID=%#&lat=%#&lon=%#", apiKey, latitude, longitude];
NSString *encodedUrl = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:encodedUrl];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url];
[theRequest setHTTPMethod:#"GET"];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
[[session dataTaskWithRequest:theRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(data != nil) {
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSLog(#"Here is the json dict: %#", jsonDict);
NSLog(#"%#", response);
}
else {
NSLog(#"error: %#", error);
}
}] resume];
Again, the request here returns the error but in Postman I get no error when I run:
api.openweathermap.org/data/2.5/weather?APPID=MY_API_KEY&lat=33.712926&lon=-117.839181
What is the issue with how I'm setting up the request?

A URL needs a scheme part. Please make sure you include a protocol such as http or https in your URL string:
NSString *urlString = [[NSString alloc] initWithFormat:#"https://api.openweathermap.org/data/2.5/weather?APPID=%#&lat=%#&lon=%#", apiKey, latitude, longitude];

Related

NSURLSession Request returns 404 but works fine on Postman

NSString *URLString = #"http://api.sandbox.africastalking.com/version1/airtime/send";
NSString *encodedString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
NSURL *url = [NSURL URLWithString:encodedString];
NSDictionary *body = #{
...
};
// convert the dictionary into json data
NSError *error;
NSData *JSONData = [NSJSONSerialization dataWithJSONObject:body options:0 error:&error];
// Create a post request with the json as a request body.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = #"POST";
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
request.HTTPBody = JSONData;
// create the task.
NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSLog(#"Status code: %li", (long)((NSHTTPURLResponse *)response).statusCode);
NSLog(#"Response: %#", response);
NSString *responseText = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Response Text: %#", responseText);
} else {
NSLog(#"Error: %#", error.localizedDescription);
}
}];
[task resume];
The code returns "The requested resource could not be found" 404 as response but when I try this request in my REST client (Postman) it works fine.
Try a url with the URLWithString method
NSURL *url = [NSURL URLWithString:#"http://api.sandbox.africastalking.com/version1/airtime/send"];

IOS: kCFErrorDomainCFNetwork error -1002. Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL"

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];

POST base 64 image string to a server on iOS

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.

iOS Today Extension POST request to Google Directions API

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

Authentication Error with GitHub API on iOS

I am working with GitHub's REST API for iOS and am having trouble getting it to work correctly with basic authentication. I have written the following code to view a users GitHub repositories:
NSString *requestString = [NSString stringWithFormat:#"https://%#:%##api.github.com/user/repos",userName,password];
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *strData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", strData);
}];
[dataTask resume];
I am getting the following response back:
{"message":"Requires authentication","documentation_url":"https://developer.github.com/v3"}
However when I do the following in my terminal:
curl -i GET https://userName:password#api.github.com/user/repos
I get the expected result back from GitHub. I'm not sure what authentication I am missing for my iOS app because I don't have anything in my curl statement that I don't have in my iOS code. Any help explaining what I'm missing is greatly appreciated.
It seems that something in NSURLSession doesn't like the username/password encoded in the URL (and to be honest, it isn't very secure as it can be exposed in proxy logs and is also prone to problems on the server side), so you have to encode the authorisation details into the HTTP headers.
This worked for me -
NSString *requestString = #"https://api.github.com/user/repos";
NSURL *url = [NSURL URLWithString:requestString];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSData *userPasswordData = [[NSString stringWithFormat:#"%#:%#", userName, password] dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];
NSString *authString = [NSString stringWithFormat:#"Basic %#", base64EncodedCredential];
NSURLSessionConfiguration *sessionConfig=[NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.HTTPAdditionalHeaders=#{#"Authorization":authString};
self.session=[NSURLSession sessionWithConfiguration:sessionConfig];
NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:req completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *strData = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"%#", strData);
}];
[dataTask resume];
I can see two possible reasons:
your password contains special characters that needs to be "percent escaped": see "NSString method to percent escape '&' for URL"
the ## is somehow misinterpreted: you can try to POST the username and password as in this question

Resources