Network requests are failing - NSURLSession - App Sandbox - Xcode 9 - objective-c

I have a simple GET request that I am trying to run in my macOS application. However I keep getting the following error:
A server with the specified hostname could not be found.
The URL I am trying to download JSON data from is:
https://suggestqueries.google.com/complete/search?client=safari&q=mercedes
If I test it in my browser or in an online API tester website (such as Hurl.it), the request works fine. A JSON file is then downloaded automatically.
However running the request via my macOS app does not work. Here is my code:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://suggestqueries.google.com/complete/search?client=safari&q=mercedes"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:#"GET"];
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
[[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(#"Data: %#", data);
NSLog(#"Response: %#", response);
NSLog(#"Error: %#", error);
}] resume];
Here is the full error log:
dnssd_clientstub ConnectToServer: connect()-> No of tries: 1
dnssd_clientstub ConnectToServer: connect()-> No of tries: 2
dnssd_clientstub ConnectToServer: connect()-> No of tries: 3
dnssd_clientstub ConnectToServer: connect() failed
path:/var/run/mDNSResponder Socket:6 Err:-1 Errno:1 Operation not
permitted 2017-10-27 09:58:31.610493+0100 search suggestions
[] nw_resolver_create_dns_service_locked
DNSServiceCreateDelegateConnection failed: ServiceNotRunning(-65563)
TIC TCP Conn Failed [1:0x600000164080]: 10:-72000 Err(-65563)
Task <12212C3B-8606-49C2-BD72-AEBD575DB638>.<1> HTTP load failed
(error code: -1003 [10:-72000])
Task
<12212C3B-8606-49C2-BD72-AEBD575DB638>.<1> finished with error - code:
-1003
Data: (null)
Response: (null)
Error: Error Domain=NSURLErrorDomain Code=-1003 "A server with the specified
hostname could not be found." UserInfo={NSUnderlyingError=0x60400004fa20 {Error
Domain=kCFErrorDomainCFNetwork Code=-1003 "(null)"
UserInfo={_kCFStreamErrorCodeKey=-72000,
_kCFStreamErrorDomainKey=10}}, NSErrorFailingURLStringKey=https://www.suggestqueries.google.com/complete/search?client=safari&q=mercedes,
NSErrorFailingURLKey=https://www.suggestqueries.google.com/complete/search?client=safari&q=mercedes,
_kCFStreamErrorDomainKey=10, _kCFStreamErrorCodeKey=-72000, NSLocalizedDescription=A server with the specified hostname could not
be found.}
What am I doing wrong? It's just a simple GET request, I don't understand why the data won't load.

I figured out what was wrong, even though I had set Allow Arbitrary Loads to YES, this is no longer enough to enable network requests.
There is a new setting in Xcode 9 called App Sandbox that can stop incoming/outgoing network connections too! I had to turn this setting off and then all network requests started to work.

In XCode 11.5 I had to check these two flags

You have to turn off the "App Sandbox".
Go to:
xcode Project-> Capabilities -> App SandBox

Please try below code
#property (nonatomic, strong) NSURLConnection *connection;
NSMutableString *urlString = [NSMutableString stringWithString:BASE_URL];
[urlString appendFormat:#"%#",apiName]; //apiName —> Webservice Name
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[request setValue:#"gF!DeEfFrjqaAaD$gH#Mn#w(z" forHTTPHeaderField:#"PC-API-KEY"]; //Optional Parameter pass if required key
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPMethod:#"POST"]; //if your required Get than [request setHTTPMethod:#"GET"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[parameterDict toJSON]];
[request setTimeoutInterval:45.0];
self.connection =[[NSURLConnection alloc] initWithRequest:request delegate:self];
if (self.connection) {
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
self.downLoadedData = [NSMutableData data];
}

Related

NSUrlSession proxy request fails with error code 310 (kCFErrorHTTPSProxyConnectionFailure)

I'm trying to send a POST request to a specific URL through a proxy server. To test that the code I'm writing is working, I installed squidman on my machine and started a proxy server on port 33074. I tested the proxy server by changing the network settings to use the proxy when making HTTP/HTTPS requests and it's working ok.
Now I wrote the following code:
NSDictionary* proxyConfig = #{
(NSString*) kCFNetworkProxiesHTTPSEnable: #(1),
(NSString*) kCFNetworkProxiesHTTPSProxy: #"127.0.0.1",
(NSString*) kCFNetworkProxiesHTTPSPort: #"33074",
};
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
[sessionConfig setTimeoutIntervalForRequest:60];
[sessionConfig setConnectionProxyDictionary:proxyConfig];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:#"https://the-host-where-im-posting"]];
[request setHTTPMethod:#"POST"];
[request setValue:[[NSString alloc] initWithFormat:#"%lu",length] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:data];
NSURLSession *session = [self createHttpSession];
NSURLSessionDataTask* dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
if(httpResponse.statusCode == 200){
//...
} else {
LOGERROR(#"Error: %#", error);
}
}
The problem is that the request is not successfull and the following error is logged:
Error: Error Domain=kCFErrorDomainCFNetwork Code=310 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2096, _kCFStreamErrorDomainKey=4}
Additional Info:
1. It should be noted that the requests submits perfectly without setting the proxyConfig dictionary.
2. A similar error gets reported if I'm trying to submit the request using HTTP through the proxy (by correspondingly changing the keys in the proxyConfig dictionary) with a small diff in the Err Code and _kCFStreamErrorCodeKey: 306 instead of 310 and -2094 instead of -2096.
3. The process making the request runs as a daemon.
What exactly am I doing wrong ? What am I missing ?
I was setting the kCFNetworkProxiesHTTPSPort field from the proxyConfig dictionary to a value of type NSString. After carefully reading the documentation for it I observed the following:
Key for the port number associated with the HTTPS proxy; value is a CFNumber which is the port number.
The library was encountering an object that was not a CFNumber and was using the default port for HTTPS communication to connect to the proxy instead (443). That's bad error handling imho. It was essentially silently trying to make a request using a port that I was not aware of. Changing the proxyConfig dictionary to the following fixed the problem:
NSDictionary* proxyConfig = #{
(NSString*) kCFNetworkProxiesHTTPSEnable: #(1),
(NSString*) kCFNetworkProxiesHTTPSProxy: #"127.0.0.1",
(NSString*) kCFNetworkProxiesHTTPSPort: #(33074),
};

overwrite JSON data on server

My app is pulling down a JSON file from my server (GoDaddy) and parsing it into an array. The user is then able to add a new record to the existing JSON. I'm running into issues when I try to post all of the data back to server.
To be clear, I'm trying to overwrite the existing file that's on the server with the new data. I know FTP isn't the direction I need to be going, but I'm not using a database of any kind. Just files on the server.
I've made sure the JSON is valid and I've called GoDaddy to make sure I don't need to change any permissions. I've used this directory for FTP before.
Could it be that my REMOTE_PATH_TO_ROOT_APP_FOLDER uses FTP credentials? If so, what URL do I need to use?
- (void)postExamplesDictionaryToServer:(nonnull NSString *)dName
:(nonnull NSString *)rName
:(nonnull NSData *)jsonData
{
NSString *userFileURLString = [NSString stringWithFormat:#"%#/%#/%#TESTER.json", REMOTE_PATH_TO_ROOT_APP_FOLDER, dName, rName];
NSURL *userFileURL = [NSURL URLWithString:userFileURLString];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[jsonData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:userFileURL];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:jsonData];
[[self.session uploadTaskWithRequest:request fromData:jsonData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"Error: %#", error);
}] resume];
}
EDIT: I logged the NSERROR passed to the completion handler and got this:
Error: (null)
BUT...If I change the URL to a file that doesn't already exist on the server, I get this:
Error: Error Domain=NSURLErrorDomain Code=-1008 "resource unavailable"
UserInfo={NSUnderlyingError=0x7fca8ad44280 {Error Domain=kCFErrorDomainCFNetwork Code=-1008 "(null)"},
NSErrorFailingURLStringKey=ftp://*****:*****#ftp.*****.com/public_html/app/******/File.json,
NSErrorFailingURLStringKey=ftp://*****:*****#ftp.*****.com/public_html/app/******/File.json, NSLocalizedDescription=resource unavailable}
Does this mean it's not attempting to do an upload task, only a request somehow?

ASIHTTPRequest not connecting using proxy parameters in iOS 5

The error code I'm receiving:
Error Domain=ASIHTTPRequestErrorDomain Code=1 "A connection failure occurred" UserInfo=0x6993280 {NSUnderlyingError=0x6d520c0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 306.)"
I do not have option but ASIHTTPRequest. I have already developed the app and cannot use the any alternatives.
Currently we are using iOS version 5.1.1
I have developed the app one year back with the same code for iOS 3 and it was working properly. Now same code is failed to work. I suspect this happens with the latest iOS versions.
This code works well without proxy settings but not with proxy settings.
_method = [NSStringstringWithFormat:#"http://%#%#", _settings.ServerLocation, _settings.WebServicePath];
NSLog(_method);
NSString *soapMessage = [NSStringstringWithFormat:#"%#%#%#",
#"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"
"<soap:Body>\n",
parameters,
#"</soap:Body>\n"
"</soap:Envelope>\n"];
//NSLog(#"soapMessage : %#",soapMessage);
NSURL *url = [NSURLURLWithString:_method];
ASIHTTPRequest *request = [ASIHTTPRequestrequestWithURL:url];
if(_settings.IsProxy)
{
[request setProxyHost:_settings.HostIP];
[request setProxyPort:(NSInteger)_settings.Port];
}
constchar *utfString = [soapMessage UTF8String];
NSMutableData *req = [NSDatadataWithBytes:utfString length:strlen(utfString)];
[request addRequestHeader:#"Content-Type"value:#"text/xml; charset=utf-8"];
[request addRequestHeader:#"Content-Length"value:[NSStringstringWithFormat:#"%d", [soapMessage length]]];
[request addRequestHeader:#"SOAPAction"value:action];
if(_settings.IsProxy)
{
[request addRequestHeader:#"Host"value:_settings.HostIP];
}
[request setPostLength:[soapMessage length]];
[request setRequestMethod:#"POST"];
[request setPostBody:req];
[request setTimeOutSeconds:5];
[request setNumberOfTimesToRetryOnTimeout:1];
if(_settings.IsProxy)
{
if([_settings.Usernamelength] > 0)
{
[request setProxyUsername:_settings.Username];
}
if([_settings.Passwordlength] > 0)
{
[request setProxyPassword:_settings.Password];
}
}
//[request setValidatesSecureCertificate:NO];
[request setDelegate:self];
[request startAsynchronous];
I have downloaded the ASIHTTPRequest Libraries and it worked as i expected.
before it works, i have removed below line of code
[request addRequestHeader:#"Host"value:_settings.HostIP];

Asynchronous POST to server

The goal is to do a simple username/password authentication by querying a database. Until the connection is working decently my php destination file simply has following code:
echo "Posted: " . $_POST['email'];
The code to do this synchronously is this:
NSString *post = [[NSString alloc] initWithFormat:#"email=%#&password=%#", self.email.text, ..]; // .. simplified keychainItem
NSData *postEncoded = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
NSString *postLength = [NSString stringWithFormat:#"%d", [postEncoded length]];
NSURL *url = [NSURL URLWithString:#"http://eng.studev.groept.be/web2.0/a11_web02/improver/app/testPost"];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postEncoded];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *encodedData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *data=[[NSString alloc]initWithData:encodedData encoding:NSUTF8StringEncoding];
NSLog(#"Data? %#",data);
The correct value is shown as an echo. But when trying to do this asynchronously, I get following php error: "Undefined index: email".
I try to start the asynchronous request with this line:
[[NSURLConnection connectionWithRequest:request delegate:self] start];
Then, I have the delegate method connection:didReceiveResponse, but there I cannot seem to get the data out... Or do I need another delegate method? Also, how 'safe' is it to check the result of your query by using just an echo (do I need/want a stream maybe?) ??
Tia
EDIT
Problem related to the server, not to objective-C code. Asked a new question to reach the correct audience: $_POST remaining empty
#ott is on the right track, I'll try to clarify.
You don't need start as he says. It's benign as the connection will start automatically.
initWithRequest:delegate and connectionWithRequest:delegate: are equivalent except for the retain state of the new connection object.
The real problem is b/c you are using connectionWithRequest:delegate the returned connection is autoreleased at the end of the run loop and you are not retaining it in a property. Therefore, the connection never starts.
The solution is to add a property #property (nonatomic, retain) NSURLConnection *connection to your class and set this property to the connection returned from connection:withRequest:
You then release the connection in the completion methods connection:didFinishLoading and connection:didFailWithError:.
The start is wrong here. Simply use
self.connection = [NSURLConnection connectionWithRequest:request delegate:self];
with NSURLConnection *connection; defined. See the class reference for connectionWithRequest. start is to be used with initWithRequest:delegate:.

How to authenticate on twitter from iphone using asihttp?

I used the asihttp library to connect to twitter.
The idea is to send a login request, get the response and extract the session ID/auth code from the response's cookie header. Then you can use that session ID/auth code for consecutive calls.
I don't obtain the auth_code because the authentication fails. how can I fix this?
the code is below:
- (void) login {
NSString *username = #"user";
NSString *password = #"pass";
NSURL *url = [NSURL URLWithString:#"https://twitter.com/sessions?phx=1"];
ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request addRequestHeader:#"User-Agent" value: #"ASIHTTPRequest"];
[request setPostValue:username forKey:#"session[username_or_email]"];
[request setPostValue:password forKey:#"session[password]"];
[request setDelegate: self];
[request setDidFailSelector: #selector(loginRequestFailed:)];
[request setDidFinishSelector: #selector(loginRequestFinished:)];
[request startAsynchronous];
}
- (void)loginRequestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
NSLog(#"login request failed with error: %#", [error localizedDescription]);
}
- (void)loginRequestFinished:(ASIHTTPRequest *)request {
NSString *responseString = [[request responseHeaders] objectForKey:#"Set-Cookie"];
NSLog(#"%#",responseString);
}
I tried to connect from shell and it works.
curl -d 'session[user_or_emai]=user&session[password]=pass' https://twitter.com/sessions
Don't scrape twitter.com. It will end with you getting suspended. Instead use the approved API to integrate with Twitter. You can read about how authentication works with Twitter's API, how you can use xAuth to jumpstart authentication with a users password, and the open source code to help get you started.