The network connection is lost only in iOS 13.1.3 (Alamofire) - ios

My app connects to a localhost API through Alamofire. I have implemented URL Scheme, so when I click the link from iMessage it opens my app and in viewDidLoad() it connects to the API. For some reason I am getting following error only in iOS 13.1.3 but it is working smoothly in iOS 12.4. All I am testing in real devices.
Error:
2019-10-21 10:32:13.059194+0530 TestAPI[882:164673] [] nw_read_request_report [C5] Receive failed with error "Software caused connection abort"
2019-10-21 10:32:13.060020+0530 TestAPI[882:164673] Task <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4> HTTP load failed, 363/0 bytes (error code: -1005 [4:-4])
2019-10-21 10:32:13.076737+0530 TestAPI[882:164603] Task <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4> finished with error [-1005] Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x283d13840 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x2810a9a40 [0x1d42775e0]>{length = 16, capacity = 16, bytes = 0x100293ddc0a808680000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=http://192.168.8.104:37853/auth/test, NSErrorFailingURLKey=http://192.168.8.104:37853/auth/test, _kCFStreamErrorDomainKey=4}
2019-10-21 10:32:13.590311+0530 TestAPI[882:164306] FBSDKLog: Missing [FBSDKAppEvents appID] for [FBSDKAppEvents publishInstall:]
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x283d13840 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x2810a9a40 [0x1d42775e0]>{length = 16, capacity = 16, bytes = 0x100293ddc0a808680000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <45115A48-58C7-49EA-AB5D-2C6708E3C036>.<4>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=http://192.168.8.104:37853/auth/test, NSErrorFailingURLKey=http://192.168.8.104:37853/auth/test, _kCFStreamErrorDomainKey=4}
Here is the Code:
override func viewDidLoad()
{
super.viewDidLoad()
txtLable.text = "test"
let testServices = TestService()
let test: Parameters = [
"test": "test"
]
testServices.TestNonSecureConnection(parameters: test, completionHandler: {(returnUserVerificationStatus) -> Void in
if(returnUserVerificationStatus != "failed")
{
self.txtLable.text = returnUserVerificationStatus
}else{
print("failed")
}
})
}
class TestService
{
func TestNonSecureConnection(parameters: Parameters, completionHandler: #escaping (_ returnUserVerificationStatus: String)-> Void )
{
var headers: HTTPHeaders = [:]
var resultString = ""
let url = URL(string: Config.LOGIN_SERVER_URL + "/auth/test")!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = "POST"
do {
urlRequest.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
} catch {
// No-op
}
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(urlRequest)
.responseString() { response in
switch response.result {
case .success:
resultString = response.result.value!
completionHandler(resultString)
case .failure(let error):
print(error)
}
}
}
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
self.window = UIWindow(frame: UIScreen.main.bounds)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
self.scheme = url.scheme
self.path = url.path
self.query = url.query
let viewController = storyBoard.instantiateViewController(withIdentifier: "viewcontroller") as! ViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()
return true
}

Essentially, the underlying NSURLRequest is trying to re-use an HTTP connection that has been dropped by the server. This is apparently caused because the client libraries and your server expect different lifespans for the connection. Or something. Honestly, I'm not 100% sure on the why, but the solutions below all suggest that's what is happening.
There are 3 different ways to solve this one:
Disable KeepAlive on your server
This will cause new connections to be re-created for each new request. Depending on the pattern in which you talk to the server
this may be inconsequential ... or it may be performance concern.
Leave KeepAlive ON but make KeepAliveTimeout longer than 30s
This is
the opposite tradeoff as #1. It will be faster and if you're hitting
the server a lot you may notice it.
This will however cause your server to build up connections and reduce the number of concurrent users you can support. The performance impact of either choice
depends somewhat on what server you're running and you should be
able to decide with a little googling around for "KeepAlive best
practices".
Detect the error code and immediately retry the same query.
When you receive this error - check the error code and immediately retry the
same request. If the error is caused by using a defunct connection, the new query will create a new connection automagically and should work. If the network is genuinely gone the you've got bigger problems.
It's possible that this error will come from other sources, but I've tried all 3 of these approaches and each one solved the issue (obviously with different tradeoffs).
refer to : this post

Related

Request not firing when returning to app from background

I'm returning to my app which is in the background from a successful payment from another app. When returning, a patch request should be fired to change status from available to sold. The problem is that the request is never fired.
I use alamofire session manager to make the request. And the function making the request is used all over the project and it works. It is also not a server error or a threading error as it runs on the main thread and the server works through curl / swagger.
It seems to me that the app does not have internet connection or something of the sort when returning to the app. Loggs can be found down below. The request has been succesfully fired a couple of times, which makes be believe in the internet connection theory.
Here are some selected parts of the code.
lazy var manager: SessionManager = {
let sessionManager = Alamofire.SessionManager.default
sessionManager.session.configuration.timeoutIntervalForRequest = 40
sessionManager.adapter = OauthHandler.sharedInstance
sessionManager.retrier = OauthHandler.sharedInstance
return sessionManager
}()
func authenticateRequestWithRouter(_ router: BaseRouter, shouldShowErrorAlert: Bool = true, _ completion: requestResponse?) {
let request = router.asURLRequest()
manager.request(request).validate().responseJSON() { [weak self] response in
switch response.result {
case .success(let data):
completion?(true, data, nil)
case .failure(let error):
if shouldShowErrorAlert,
let errorMessage = self?.parseErrorMessage(fromData: response.data, request: request) {
self?.showErrorAlert(message: errorMessage)
}
completion?(false, response.data, error)
}
}
}
Logs that have been occuring:
Returning ENOTCONN because protocol has not yet been set up
nw_connection_copy_connected_local_endpoint [C7] Connection has no
local endpoint
HTTP load failed (error code: -1005 [1:57])
Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
Domain=NSPOSIXErrorDomain Code=53 "Software caused connection abort"
nw_protocol_boringssl_error(1584) [C1.1:2][0x102838b30] Lower protocol
stack error: 53

Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost

I am getting this error when using SwiftyBeaver logger, which tries to send data to the cloud via this code:
func sendToServerAsync(str: String?, complete: (ok: Bool, status: Int) -> ()) {
if let payload = str, let queue = self.queue {
// create operation queue which uses current serial queue of destination
let operationQueue = NSOperationQueue()
operationQueue.underlyingQueue = queue
let session = NSURLSession(configuration:
NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: nil, delegateQueue: operationQueue)
// assemble request
let request = NSMutableURLRequest(URL: serverURL)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// basic auth header
let credentials = "\(appID):\(appSecret)".dataUsingEncoding(NSUTF8StringEncoding)!
let base64Credentials = credentials.base64EncodedStringWithOptions([])
request.setValue("Basic \(base64Credentials)", forHTTPHeaderField: "Authorization")
// POST parameters
let params = ["payload": payload]
do {
request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: [])
} catch let error as NSError {
toNSLog("Error! Could not create JSON for server payload. \(error)")
}
//toNSLog("sending params: \(params)")
//toNSLog("\n\nbefore sendToServer on thread '\(threadName())'")
sendingInProgress = true
// send request async to server on destination queue
let task = session.dataTaskWithRequest(request) {
_, response, error in
var ok = false
var status = 0
//toNSLog("callback of sendToServer on thread '\(self.threadName())'")
if let error = error {
// an error did occur
self.toNSLog("Error! Could not send entries to server. \(error)")
} else {
if let response = response as? NSHTTPURLResponse {
status = response.statusCode
if status == 200 {
// all went well, entries were uploaded to server
ok = true
} else {
// status code was not 200
var msg = "Error! Sending entries to server failed "
msg += "with status code \(status)"
self.toNSLog(msg)
}
}
}
return complete(ok: ok, status: status)
}
task.resume()
}
}
The strange thing is it works for the first two or three log entries, and then stops due to the above error. I tried to reset content and settings on the simulator and reboot my simulator (as suggested in Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost.") but that just fixes it temporarily--after the first 2-3 log entries, it starts failing again.
I tried debugging this for hours with the creator of SwiftBeaver last night, but we couldn't get it to work. Seems like not many people are seeing this issue.
I tried removing my Wifi connection and reconnecting, but that didn't work either.
Any guidance on this would be much appreciated.
FYI, I'm using Swift 2 and XCode 7.3.
This is probably caused by HTTP keep-alive support being seriously buggy in the iOS simulator. See:
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
for more details, but the short answer is to disable keep-alive on the server that you use when doing simulator testing, or better yet, add some logic that immediately retries the request if it sees that particular error.

Error Code=-1005 "The network connection was lost." in Swift while consuming Web Service

I'm working on a iOS project in Swift 2.0, which has Web service calls, these services are slow to respond and that is normal, can be up to 1 minute or a little more, when i call the service 70% of the time it answers with the error "the network connection was lost." The tests were conducted in both simulator and different phone devices and iPad and the result is the same. The network connection is strong and the same application was also created on Android and working properly almost 100% of the time.
The way I call services from any view is as follows:
#IBAction func contratarAct(sender: AnyObject) {
conexion.delegate = self
loadingView = MEXLoadingView(delegate: self, title: "Espere por favor", percent: false, view: self.view)
self.loadingView.showAnimated(true)
let url = urlServicios.urlBaseServicios + "/" + idSolicitud + "/" + idNoCliente + "/CONTRATO"
conexion.consultaServicioGET(url, httpMethod: "PUT")
}
And the method that is executed is as follows:
func consultaServicioGET(url : String, httpMethod : String ){
let urlString = url
let request = NSMutableURLRequest(URL: NSURL(string: urlString)!)
request.timeoutInterval = 540
request.cachePolicy = NSURLRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData
request.addValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
var session = NSURLSession.sharedSession()
request.HTTPMethod = httpMethod
let urlconfig = NSURLSessionConfiguration.defaultSessionConfiguration()
urlconfig.timeoutIntervalForRequest = 540
urlconfig.timeoutIntervalForResource = 540
session = NSURLSession(configuration: urlconfig, delegate: self, delegateQueue: nil)
let task = session.dataTaskWithRequest(request , completionHandler: {
(data:NSData?, response:NSURLResponse?, error:NSError?) in
if error != nil {
let jsonError : NSDictionary = NSDictionary()
self.delegate?.respuestaServicioGET!(jsonError, mensaje: "\(error!.localizedDescription)")
return
}
let jsonString = NSString(data: data!,encoding: NSASCIIStringEncoding)
let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
let json: NSDictionary = try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary
if (json.isKindOfClass(NSDictionary) ){
self.delegate?.respuestaServicioGET!(json, mensaje: "OK")
}else{
let jsonError : NSDictionary = NSDictionary()
self.delegate?.respuestaServicioGET!(jsonError, mensaje: "ERROR")
}
})
task.resume()
}
the error displayed is:
error=Optional(Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x7fbde5f51df0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://particulares-gw-obparticularesmx-pre.appls.cto2.paas.gsnetcloud.com:443/OPB/57dadf7de4b0ac2e518de44a/57dadf7de4b06c6b04ef0dcf/CONTRATO, NSErrorFailingURLKey=https://particulares-gw-obparticularesmx-pre.appls.cto2.paas.gsnetcloud.com:443/OPB/57dadf7de4b0ac2e518de44a/57dadf7de4b06c6b04ef0dcf/CONTRATO, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.})
I add some code like the following:
urlconfig.timeoutIntervalForRequest = 540
urlconfig.timeoutIntervalForResource = 540
Trying to get more "timeout" but this is not looks like a timeout.
I can not get out of this error for days, any help will be greatly appreciated. I'm desperate.
If you're expecting a socket to stay open for minutes at a time, you're in for a world of hurt. That might work on Wi-Fi, but on cellular, there's a high probability of the connection glitching because of tower switching or some other random event outside your control. When that happens, the connection drops, and there's really nothing your app can do about it.
This really needs to be fixed by changing the way the client requests data so that the responses can be more asynchronous. Specifically:
Make your request.
On the server side, immediately provide the client with a unique identifier for that request and close the connection.
Next, on the client side, periodically ask the server for its status.
If the connection times out, ask again.
If the server says that the results are not ready, wait a few seconds and ask again.
On the server side, when processing is completed, store the results along with the identifier in a persistent fashion (e.g. in a file or database)
When the client requests the results for that identifier, return the results if they are ready, or return a "not ready" error of some sort.
Have a periodic cron job or similar on the server side to clean up old data that has not yet been collected.
With that model, it doesn't matter if the connection to the server closes, because a subsequent request will get the data successfully.
I faced the same issue and I am attaching a screenshot of the resolution to show how I resolved the issue.
In my case, the issue was that the API requests are blocked from the server Sucuri/Cloudproxy (Or you can say firewall service). Disabling the firewall resolved the issue
I don't why but it's works when I add sleep before my request:
sleep(10000)
AF.request(ViewController.URL_SYSTEM+"/rest,get_profile", method: .post, parameters: params, encoding: JSONEncoding.default , headers: headers).responseJSON { (response) in
}
I faced this issue and spend more than 1 week to fix this. AND i just solved this issue by changing Wifi connection.

Data task with URL timed out

I am trying to access a website. I am using a dataTaskWithURL request.
Here is my code:
let task = NSURLSession.sharedSession().dataTaskWithURL(url, completionHandler: { (data, response, error) in
print("2")
if let urlContent = data {
print("3")
let stringContent = NSString(data: urlContent, encoding: NSUTF8StringEncoding)!
let arr = stringContent.componentsSeparatedByString("<b>The computer's solutions will appear below</b><br>")
let second = arr[1]
let newArr = second.componentsSeparatedByString("</tr></table></center><p align=\"center\">")
let results = newArr[0]
self.resultsLabel.text = results
self.stopActivity()
} else {
print(error)
self.stopActivity()
}
})
task.resume()
I have also tried running this code on the main block:
dispatch_async(dispatch_get_main_queue(), {() -> Void in
// Code
})
However, neither of these has been successful. I repeatedly get the following error
Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x7ff0a3f4c6e0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=THE URL I AM TRYING TO ACCESS, NSErrorFailingURLKey=THE URL I AM TRYING TO ACCESS, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.})
I have tried looking at this post and this one as well. However, I have not been successful with them. The website loads fairly quickly. How do I get rid of this error?
It could be caused by a number of things; If the issue is happening in the Simulator, I suggest restarting it as per the suggestions in the SO posts below:
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
Error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out."
NSURLErrorDomain Code=-1001 error when a http post request is sent
Undocumented NSURLErrorDomain error codes (-1001, -1003 and -1004) using StoreKit
How to use NSURLSessionDataTask in Swift
It might be help to print response as well to see if the HTTP headers can provide a clue.
I realized that I was using https:// instead of http://.

SoundCloud API: GET request fails with code -1005, using iOS/Alamofire

I'm working on an iOS app where SoundCloud users log in with OAuth in a web view and then the app makes HTTP requests to the SoundCloud API via Alamofire. I've successfully authenticated the user and stored their token (using ABMSoundCloudAPI), but GET requests to https://api.soundcloud.com/me are failing with a -1005 error, "The network connection was lost." This seems to be a common problem with iOS as discussed here, however resetting the simulator doesn't solve the problem for me and the problem also occurs when using a device. I've also tried:
Removing and re-adding the wifi network
Retrying the request programmatically if it fails
Adding a header with "Connection": "Close"
I see the same error in every case. Are there other headers I should try? I'm using these libraries via Cocoapods:
ABMSoundCloudAPI (0.2.1)
AFNetworking (2.6.1)
AFOAuth2Manager (2.2.0)
Alamofire (3.1.2)
SwiftyJSON (2.3.1)
Here is my code:
var retryCount = 0
func getUserInfo(token:String) {
let headers = ["Connection": "Close"]
Alamofire.request(.GET, "https://api.soundcloud.com/me?oauth_token=\(token)", parameters: ["client_id":clientId], encoding: .JSON, headers: headers)
.responseJSON { response in
guard response.result.error == nil else {
print("error calling GET on /me")
print(response.result.error)
if self.retryCount < 2 {
if let token = self.defaults.stringForKey("sc_key_token") {
self.getUserInfo(token)
++self.retryCount
}
}
return
}
guard let value = response.result.value else {
print("Error: did not receive data")
return
}
let user = JSON(value)
print("User info: " + user.description)
}
}
Error message:
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={NSUnderlyingError=0x126248c10 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={_kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=https://api.soundcloud.com/me?oauth_token=USER_TOKEN, NSErrorFailingURLKey=https://api.soundcloud.com/me?oauth_token=USER_TOKEN, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-4, NSLocalizedDescription=The network connection was lost.}
It seems that this was caused by the request encoding. When I switched from .JSON to .URL, the 1005 error went away.

Resources