Swift problem with URLSession in Watchkit XCode - ios

I got a problem with UrlSession and a .local domain.
When I send a Request to the IP address of the device in my home network it works. But when I use the .local domain for example "http://esp8266.local" it don't work and there are some errors.
On the IOS App it works fine.
This doesn't work on Watchkit but on IPhone App it works fine:
PDTask .<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_NSURLErrorFailingURLSessionTaskErrorKey=LocalDataPDTask .<1>, NSLocalizedDescription=The request timed out., _kCFStreamErrorCodeKey=-2102, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataPDTask .<1>",
"LocalDataTask .<1>"
), NSErrorFailingURLStringKey=http://esp8266.local/, _kCFStreamErrorDomainKey=4, NSErrorFailingURLKey=http://esp8266.local/}
let url = URL(string: "http://esp8266.local")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
print(response!)
if error != nil {
print("FAIL")
print(error!)
} else {
print("OKEY")
print(data!)
}
}
task.resume()
And this works fine:
let url = URL(string: "http://192.168.0.109")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
print(response!)
if error != nil {
print("FAIL")
print(error!)
} else {
print("OKEY")
print(data!)
}
}
task.resume()

Related

How to get timeout info from dataTask

I have the following code for requesting data from an external API:
var request = URLRequest(url: myURL!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { data, response, error in
if error != nil {
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
}
})
dataTask.resume()
The timeoutInterval is set to 10.0. But how can I get back info on if the request/session timed out, or how long the request/session took the complete? I will then use that info to determine which function I should call.
Any help is much appreciated!
If the error is not nil then cast error as URLError and check the code is .timeout or not. Here is the code.
var request = URLRequest(url: myURL!, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers
let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
if (error != nil) {
if let error = error as? URLError {
if error.code == .timedOut {
print("Timeout error")
}
}
print(error)
} else {
let httpResponse = response as? HTTPURLResponse
}
})
dataTask.resume()

Timeout error when post public key string with URLSession

I am creating a rsa key pair and send the public key to my api. But the post request fails with Timeout error. Following is my function for the request:
func perform<T: Decodable>(reqData: Data, with completion: #escaping (T?) -> Void) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
// insert json data to the request
request.httpBody = reqData
print("jsonData: ", String(data: request.httpBody!, encoding: .utf8) ?? "no body data")
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let error = error else {
print(error)
completion(nil)
return
}
guard let data = data else {
completion(nil)
return
}
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .secondsSince1970
completion(try? decoder.decode(T.self, from: data))
}
task.resume()
}
JSON Object sent in POST:
{
"publicKey" : "MIIBCgKCAQEA4lS13W+TXZhUXy5yB2NpeulCVb1ZSaReopeKrahjKmUx4NQxVXruEYCY3LpjZcSy8xiudVG3GBIMnPLtaMbc5WAYDj1M2OwnpNHdQ8SKtZ1tdA6iRjfOXGUa1n8FMIMKU5ynTSAiSoh+8gGrY0L6jTsCSdLO5ZU53LQFHSESM8JuBeNZozolb\/cKb38ylercVeVpo8egoA8UqHezK23VUJ23faxMmMZDJxVn5pfFedxBTLxwU65KQY8Z4izaFjuPLoGe5JZkXyYNMcrYloDCBG5m9BFiXVkoLEDmGFGfWLMJcqL+D2CszqJ4h712ZR6LYRNtIbo\/HG9KR7XCtap3QwIDAQAB"
}
I have tested the url in Postman and it works good there. But it is giving my follwoing error when I call it from my app:
Task <6AB1B692-9CBF-4E37-80C6-4F37FD43264B>.<1> finished with error [-1001] Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2102, NSUnderlyingError=0x280299c50 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <6AB1B692-9CBF-4E37-80C6-4F37FD43264B>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <6AB1B692-9CBF-4E37-80C6-4F37FD43264B>.<1>"
), NSLocalizedDescription=The request timed out., NSErrorFailingURLStringKey=http://192.168.178.205:3000/savepublickey, NSErrorFailingURLKey=http://192.168.178.205:3000/savepublickey, _kCFStreamErrorDomainKey=4}
Following is my server side code in Node.js:
app.post('/savepublickey', (req, res) => {
console.log("savepublickey");
console.log(req.body);
let data = JSON.parse(JSON.stringify(req.body, null, 2));
if (data['publicKey'] != null && data['publicKey'] != "") {
console.log("Success");
publicKey = data['publicKey'];
res.status(200).json({
"Status": "Success"
}).send();
} else {
console.log("Fail");
res.status(500).json({
"Status": "Invalid request"
}).send();
}
})

Swift URLSession.shared.dataTask GET Request -1001 returns timeout

Sending a POST request to our NGINX Server works good with URLRequest and URLSession.shared.dataTask.
I can login to my app but when I try a GET request my server has no log that the request reached him. Finally I get the timeout error. Important, I am using https. I also tried to use http for GET Requests. on my NGINX Server I set TLS to 1.2 only (I am not a system specialist, I did that in the nginx cfg file.
Error Domain=NSURLErrorDomain Code=-1001 "Zeitüberschreitung bei der Anforderung." UserInfo={NSUnderlyingError=0x60400005abe0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://myurl, NSErrorFailingURLKey=https://myurl, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=Zeitüberschreitung bei der Anforderung.}
I am sure that my code for the URLRequest and URLSession is correct because against localhost and our development environment I do not have any of those problems.
Thats my code to create my URLRequest
private func buildUrlRequest(jsonObject:[String: Any], connectionType:ConnectionTypes, url:String) -> NSMutableURLRequest? {
let jsonDataSerialized:Data
do {
jsonDataSerialized = try JSONSerialization.data(withJSONObject: jsonObject)
} catch {
return nil
}
var request:NSMutableURLRequest
if nextData {
request = URLRequest(url: URL(string: self.nextRequestPage)!) as! NSMutableURLRequest
} else {
let tString = self.mBaseUrl + url
if let encoded = tString.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed),
var finalurl = URL(string: encoded)
{
if connectionType == .GET {
var tString:String
tString=finalurl.absoluteString
tString = tString.replacingOccurrences(of: "https", with: "http")
finalurl = URL(string:tString)!
}
request = URLRequest(url: finalurl) as! NSMutableURLRequest
} else {
return nil
}
}
request.httpMethod = connectionType.rawValue // i am using enum here
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.setValue("no-cache)", forHTTPHeaderField: "Cache-Control")
request.httpBody = jsonDataSerialized
if mUser != nil && mUser.getSessionId() != nil {
request.addValue("Token " + mUser.getSessionId()!, forHTTPHeaderField: "Authorization")
}
request.cachePolicy = .reloadIgnoringLocalAndRemoteCacheData
request.timeoutInterval = 30.0
return request
}
This is how I create the task... after the method body I am using task.resume()
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in .... (and so on)
I spend more than hours to solve this problem... But I have no idea.
I am not sure if the Problem is the Server Config or the Swift code...
The major problem was jsonObject:[String: Any] !
I changed it to jsonObject:[String: Any]?
In my code I've created the body for each request no matter if it was a POST GET PUT or what ever. Without the http-body in a GET request I have no problem anymore, no timeout! I correctly receive the data as expected.
I've also found out that it is not necessary to set the nginx's or lets encrypt sll_protocols to TLS 1.2 only in my case.
I hope if someone else runs into this issue, they will find this post :)

Unsupported URL swift ios sending Http request

I'm trying to send an http request in swift.
I got a method (sendHttpRequest) that take as argument a dictionary<String,AnyObject> and trying to send a request to localhost with a little server in php. When I tap button that call this function an error occur
"Optional(Error Domain=NSURLErrorDomain Code=-1002 "unsupported URL" UserInfo={NSErrorFailingURLStringKey=46.101.145.122/salvobertoncini.com/servo.php, NSErrorFailingURLKey=46.101.145.122/salvobertoncini.com/servo.php, NSLocalizedDescription=unsupported URL, NSUnderlyingError=0x1763cef0 {Error Domain=kCFErrorDomainCFNetwork Code=-1002 "(null)"}})"
Here is the code:
func sendHttpRequests(data : Dictionary<String, AnyObject>)
{
let session = NSURLSession.sharedSession()
do
{
let request = try NSJSONSerialization.dataWithJSONObject(data, options: .PrettyPrinted)
let url = NSURL ( string : "127.0.0.1/Server/servo.php")
let finalRequest = NSMutableURLRequest(URL: url!)
finalRequest.HTTPMethod = "POST"
finalRequest.HTTPBody = request
let task = session.dataTaskWithRequest(finalRequest){ data,response,error in
if error != nil
{
print("Error -> \(error)")
}
do
{
let result = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as? [String:AnyObject]
print("Result -> \(result)")
}
catch
{
print("Error -> \(error)")
}
}
task.resume()
}
catch
{
print(error)
}
}

Image request from URL fails

I have the following code:
func getImage(urlString: String, completionHandler: UIImage -> Void) -> NSURLSessionTask {
let request = NSMutableURLRequest(URL: NSURL(fileURLWithPath: urlString)!)
println("Executing image request: \(urlString)")
return session.dataTaskWithRequest(request) {
data, response, error in
if error != nil {
println("\tGET request failed: \(error!)")
} else {
println("\tGET request succeeded!")
let response = response as NSHTTPURLResponse
if response.statusCode == 200 {
let image = UIImage(data: data)
dispatch_async(dispatch_get_main_queue()) { // dispatch naar main thread (main_queue is thread# van main thread van app)
completionHandler(image!)
}
}
}
}
}
But when I execute it, I get the following output:
Executing image request: http://i.imgur.com/rfw7jrU.gif
GET request failed: Error Domain=NSURLErrorDomain Code=-1100
"The operation couldn’t be completed. (NSURLErrorDomain error -1100.)"
UserInfo=0x14e9b200 {NSErrorFailingURLKey=file:///http:/i.imgur.com/rfw7jrU.gif,
NSErrorFailingURLStringKey=file:///http:/i.imgur.com/rfw7jrU.gif,
NSUnderlyingError=0x14d8d600 "The operation couldn’t be completed.
(kCFErrorDomainCFNetwork error -1100.)"}
I have no idea why this happens, as my nearly identical code that gets a .json file does work. I have tested this on both my device and the simulator.
This fails on all urls, not only imgur links. It also crashes before I put it into a UIImage, so that is also not the problem.
From the error message one can see that your URL is a file URL:
file:///http:/i.imgur.com/rfw7jrU.gif
and error -1100 is kCFURLErrorFileDoesNotExist (see CFNetwork Error Codes Reference).
You should replace
NSURL(fileURLWithPath: urlString)
by
NSURL(string: urlString)
// Swift 3+:
URL(string: urlString)

Resources