Alamofire:[结果]:失败:错误域= NSURLErrorDomain代码= -999“已取消”;

问题描述:

我要连接的服务正在使用自签名证书。
出于开发目的,我不想验证该链。

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

使用Swift 3和Alamofire4。
相应地固定了ATS:

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)")
        }
    }

dumpPrint的错误日志

Error log from dumpPrint


[结果] :失败:错误域= NSURLErrorDomain代码= -999已取消
UserInfo = {NSErrorFailingURLKey = https:// sub.url.com/path
NSLocalizedDescription =已取消,
NSErrorFailingURLStringKey = https ://sub.url.com/path }

URL已被屏蔽。

要保留 SessionManager 实例,您需要在传递的闭包中捕获它到 responseJSON

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
    // ...
}

否则, sessionManager 很快就会被释放,它超出范围,所有执行请求都被取消

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