Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Alamofire: [Result]: FAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled"

The service I'm connecting to is using a self signed certificate. For dev purposes I do not want to validate that chain.

Using swift 3 with Alamofire 4. Fixed the ATS accordingly:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>url.com</key>
        <dict>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

Code to connect and disable evaluation.

    let serverTrustPolicies: [String: ServerTrustPolicy] = [
        "example.domain.com": .pinCertificates(
            certificates: ServerTrustPolicy.certificates(),
            validateCertificateChain: false,
            validateHost: true
        ),
        "sub.url.com": .disableEvaluation
    ]

    let sessionManager = Alamofire.SessionManager(
        serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies)
    )

    let headers = ["Authorization": "Basic /*...*/"]

    sessionManager.request("https://sub.url.com/path", headers: headers).responseJSON { response in
        print(response.request)  // original URL request
        print(response.response) // HTTP URL response
        print(response.data)     // server data
        print(response.result)   // result of response serialization

        debugPrint(response)

        if let JSON = response.result.value {
            print("JSON: \(JSON)")
        }
    }

Error log from dumpPrint

[Result]: FAILURE: Error Domain=NSURLErrorDomain Code=-999 "cancelled" UserInfo={NSErrorFailingURLKey=https://sub.url.com/path, NSLocalizedDescription=cancelled, NSErrorFailingURLStringKey=https://sub.url.com/path}

URL has been masked.

like image 681
Sami M'Barek Avatar asked Oct 11 '16 19:10

Sami M'Barek


5 Answers

There could be a lot of reason to why your requests "cancelled".
In your case your request cancels immediately. You can refer to this issue in Alamofire repository issues

jshier commented on Oct 10, 2016

An unexpected error -999 almost always means your SessionManager was deallocated, cancelling any ongoing requests. I suggest you create a singleton value for your custom SessionManager, or perhaps just reevaluate if you really need one.

if you create a singleton value for your object it remains in memory and prevent from deallocate

and another thing that i avoid is to name your variables diffrent, a sessionManager is in Alamofire and your variable is also called sessionManager.

Alamofire 4.7 , Swift 4

import Alamofire

class Networking {

  public static let sharedManager: SessionManager = {
      let configuration = URLSessionConfiguration.default
      configuration.timeoutIntervalForRequest=20
      let manager = Alamofire.SessionManager(configuration: configuration, delegate: SessionManager.default.delegate)
      return manager
  }()
}

Alamofire 5.4.4 , Siwft 5.2

import Alamofire

class Networking {

  static let APIManager: Session = {
      let configuration = URLSessionConfiguration.default
      configuration.timeoutIntervalForRequest = 20
      let delegate = Session.default.delegate
      let manager = Session.init(configuration: configuration,
                                 delegate: delegate,
                                 startRequestsImmediately: true,
                                 cachedResponseHandler: nil)
      return manager
  }()
}
like image 189
Mohammad Reza Koohkan Avatar answered Sep 30 '22 04:09

Mohammad Reza Koohkan


self.getSessionManager().request(urlstring, method: methods, parameters: parameters, encoding: JSONEncoding.prettyPrinted, headers: Header).responseJSON(queue: nil, options: JSONSerialization.ReadingOptions.allowFragments) { (responseObject) in ... .... }.session.finishTasksAndInvalidate()

Just put the method of invalidate after task finish, means session.finishTasksAndInvalidate()

like image 25
Rajukumar Patel Avatar answered Nov 05 '22 19:11

Rajukumar Patel


To retain SessionManager instance you need to capture it in closure passed to responseJSON:

sessionManager.request("https://sub.url.com/path", headers: headers).responseJSON { response in
    let _ = sessionManager // retain
    // ...
}

Otherwise sessionManager is deallocated shortly it goes out of scope and any executing requests are cancelled.

like image 13
mixel Avatar answered Nov 05 '22 19:11

mixel


Please add this statement to the end of responseJson block:

manager.session.invalidateAndCancel()

It happens if the object of the manager is not retained till execution of the block completes, so this would ensure its retention.

Cheers!

like image 8
Jatin Nandwani Avatar answered Nov 05 '22 19:11

Jatin Nandwani


Please check in sessiondidReceiveChallenge: delegate implementation of NSURLSession. Chances are NSURLSessionAuthChallengeCancelAuthenticationChallenge is getting executed somewhere.

like image 2
john7ric Avatar answered Nov 05 '22 17:11

john7ric