Server: Ubunta with nodejs express and nginx proxy.
When using my android app everything is working fine.
When using my iOS app i get:
"error calling GET on /district Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x1c0458db0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://xxx.xxx.xxx.xxx/api/district, NSErrorFailingURLKey=http://xxx.xxx.xxx.xxx/api/district, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.}"
This error only happens when i do GET requests. I can login(POST) and add markers to my map etc. It all works. But getting data through get requests doesnt.
I think the the problem has to do with iOS having a 30sec timeout/keep alive on devices over iOS 6 or 7. It automatically sets a header to keep alive for 30 sec.
I had similar problems when working on my mac localhost server. But i fixed it by sending back a header with res.set("Connection", "close"); in my nodejs routes back to iOS. Like this:
nodejs districtRoutes.js
router.get('/api/district', passport.authenticate('jwt', { session:false }), function(req, res, next) {
log.info("inside getting districts");
District.find({}, function(err, district) {
if (err){
res.set("Connection", "close");
log.info("error getting districts");
res.status(404).json({message:"no districts found" + err});
res.end();
}else{
res.set("Connection", "close");
log.info("success getting districts");
res.json(district);
res.end();
}
});
});
swift iOS app. Inside httpRequester helper class
func getRequest (urlPath: String, body: [String:String], success: @escaping (Data, HTTPURLResponse) -> ()) {
let token: String! = KeychainWrapper.standard.string(forKey: "token")
//check if url is a proper URL string
guard let url = URL(string: baseUrl+urlPath) else {
print("Error: cannot create URL")
return
}
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "GET"
urlRequest.addValue("JWT " + token, forHTTPHeaderField: "Authorization")
//urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
//urlRequest.addValue("application/json", forHTTPHeaderField: "Accept")
let jsonData: Data
do {
jsonData = try JSONSerialization.data(withJSONObject: body)
urlRequest.httpBody = jsonData
} catch {
print("Error: cannot create JSON from body")
return
}
let task = URLSession.shared.dataTask(with: urlRequest) { (data: Data?, response: URLResponse?, error: Error?) in
guard error == nil else {
if let httpResponse = response as? HTTPURLResponse {
self.errorHandling(response: httpResponse)
}
print("error calling GET on /" + urlPath)
print(error!)
return
}
guard let responseData = data else {
print("Error: did not receive any data")
return
}
let httpResponse = response as! HTTPURLResponse
success(responseData, httpResponse)
}
task.resume()
}
I have the same code on my current ubunta server and as said, android works fine. So does post requests on iOS but not GET requests. The problem appears on booth wifi and 4g connection on iOS devices.
Let me know if there is anything else you need from me to help solve this problem.
Thanks!