UrlSession Timed out error received after POST request

I tried to Send a POST request to a website by using urlsession task and i can never get a response back after. What i can get is a error message which shows:

error=Optional(Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSErrorFailingURLStringKey=https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests/, NSErrorFailingURLKey=https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests/, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2103, NSLocalizedDescription=The request timed out.})

2018-10-11 13:35:47.594310+0200 SwishFinalTestingIOS[5264:2203153] Task <B7405BAC-9E65-4DAA-A8C6-BA5D826386D4>.<1> finished with error - code: -999

2018-10-11 13:35:47.595138+0200 SwishFinalTestingIOS[5264:2203154] Task <B7405BAC-9E65-4DAA-A8C6-BA5D826386D4>.<1> HTTP load failed (error code: -999 [1:89])


I followed this guide in stackoverflow: https://stackoverflow.com/questions/44564422/request-timed-out-with-code

but it dosen't help me to solve my problem.

i tried to extend the timeout interval to 120 but i still can't load the data.

When i run my code, i will stuck at session.dataTask(with: request) and then my request time running out.


my Info.plist:

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
        <key>NSExceptionDomains</key>
        <dict>
            <key>mss.cpc.getswish.net</key>
            <dict>
                <key>NSExceptionAllowsInsecureHTTPLoads</key>
                <true/>
                <key>NSIncludesSubdomains</key>
                <true/>
            </dict>
        </dict>
    </dict>
</dict>


my post request code:

let url = URL(string: "https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests/")!
        let params = [
            "payeePaymentReference": "0123456789",
            "callbackUrl": "https://example.com/api/swishcb/paymentrequests",
            "payeeAlias": "1231181189",
            "amount": "100",
            "currency": "SEK",
            "message": "Kingston USB Flash Drive 8 GB"
        ]
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        var headers = request.allHTTPHeaderFields ?? [:]
        headers["Content-Type"] = "application/json"
        request.allHTTPHeaderFields = headers
        guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: []) else {
            return
        }
        request.httpBody = httpBody
        print("jsonData: ", String(data: request.httpBody!, encoding: .utf8) ?? "no body data")
        // Create and run a URLSession data task with our JSON encoded POST request
        let config = URLSessionConfiguration.default
        config.timeoutIntervalForResource = 120
        config.timeoutIntervalForRequest = 120
        let session = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue.current)
        let task = session.dataTask(with: request) { (data, response, error) in
            guard error == nil && data != nil else {
                print("error=\(String(describing: error))")
                return
            }
            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
                return
            }
            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)!
            let responseStringForJson = "[\(responseString)]"
            print("result = \(String(describing: responseStringForJson))")
        }
        task.resume()

This is the format for sending the POST request code:

https://imgur.com/a/dpIX087

Replies

The server requested a certificate when I sent an empty request. Have you gotten a certificate for your app from the server?

May be you have a problem with the session configuration.


Could you try replacing lines 24 and 25 by

let task = URLSession.shared.dataTask(with: url) { data, response, error in

Possibly because the call back url is a non-existent domain.

See line 4 in your sample code.

Sorry, yes, the server do require a certificate, but that part is already fixed. The problem for now is when i send the post request, it just make the current request timed out.

the callBackUrl is optional to add to the parameter, sorry i didn't tell that.

i need to use a UrlSessiondelegate to check the server challenge, that part i can pass it. but after that i get timed out.

How have you checked if you really fixed that part correctly ?


Anyway, while you are hiding such a very important things from us, you would not be able to get a useful response.

I'm not trying to hide it, here is the code for urlsession:

func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        let protectionSpace = challenge.protectionSpace
        print(protectionSpace.host)
        print(protectionSpace.authenticationMethod)
        NSLog("task challenge %@", protectionSpace.authenticationMethod)
        switch (protectionSpace.authenticationMethod, protectionSpace.host) {
        case (NSURLAuthenticationMethodServerTrust, "mss.cpc.getswish.net"):
            if self.shouldTrustSwish(protectionSpace: protectionSpace) {
                let credential = URLCredential(trust: protectionSpace.serverTrust!)
                completionHandler(.useCredential, credential)
                print("i'm here")
            } else {
                completionHandler(.cancelAuthenticationChallenge, nil)
            }
        case (NSURLAuthenticationMethodClientCertificate, "mss.cpc.getswish.net"):
            let identity = Bundle.main.identity(named: "swish", password: "swish")
            let credential = URLCredential(identity: identity, certificates: nil, persistence: .forSession)
            completionHandler(.useCredential, credential)
            print("i'm here too")
        default:
            completionHandler(.performDefaultHandling, nil)
        }
    }

output:

jsonData: {"callbackUrl":"https:\/\/example.com\/api\/swishcb\/paymentrequests","amount":"100","payeeAlias":"1231181189","currency":"SEK"}

mss.cpc.getswish.net

NSURLAuthenticationMethodServerTrust

2018-10-12 10:30:57.810494+0200 SwishFinalTestingIOS[5567:2324822] task challenge NSURLAuthenticationMethodServerTrust

i'm here

mss.cpc.getswish.net

NSURLAuthenticationMethodClientCertificate

2018-10-12 10:30:57.829375+0200 SwishFinalTestingIOS[5567:2324822] task challenge NSURLAuthenticationMethodClientCertificate

i'm here too

2018-10-12 10:30:57.884619+0200 SwishFinalTestingIOS[5567:2324859] [BoringSSL] boringssl_context_alert_callback_handler(3747) [C1.1:2][0x127e1abc0] Alert level: fatal, description: handshake failure

2018-10-12 10:30:57.884668+0200 SwishFinalTestingIOS[5567:2324859] [BoringSSL] boringssl_session_errorlog(224) [C1.1:2][0x127e1abc0] [boringssl_session_handshake_incomplete] SSL_ERROR_SSL(1): operation failed within the library

2018-10-12 10:30:57.884687+0200 SwishFinalTestingIOS[5567:2324859] [BoringSSL] boringssl_session_handshake_error_print(205) [C1.1:2][0x127e1abc0] 4964073992:error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.202.1/ssl/tls_record.cc:586:SSL alert number 40

2018-10-12 10:30:57.884699+0200 SwishFinalTestingIOS[5567:2324859] [BoringSSL] boringssl_context_get_error_code(3504) [C1.1:2][0x127e1abc0] SSL_AD_HANDSHAKE_FAILURE

2018-10-12 10:30:57.887256+0200 SwishFinalTestingIOS[5567:2324859] TIC TCP Conn Failed [1:0x280d80180]: 3:-9824 Err(-9824)

2018-10-12 10:30:57.887638+0200 SwishFinalTestingIOS[5567:2324859] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)

2018-10-12 10:30:57.887653+0200 SwishFinalTestingIOS[5567:2324859] Task <40480D06-2D56-4805-93FD-F8B8B0E1E5A2>.<1> HTTP load failed (error code: -1200 [3:-9824])

2018-10-12 10:30:57.887738+0200 SwishFinalTestingIOS[5567:2324861] Task <40480D06-2D56-4805-93FD-F8B8B0E1E5A2>.<1> finished with error - code: -1200

Error Optional(Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x280a84f30>, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824, NSErrorPeerCertificateChainKey=(

"<cert(0x128850000) s: mss.cpc.getswish.net i: GeoTrust RSA CA 2018>",

"<cert(0x128850a00) s: GeoTrust RSA CA 2018 i: DigiCert Global Root CA>"

), NSUnderlyingError=0x2836d7a80 {Error Domain=kCFErrorDomainCFNetwork Code=-1200 "(null)" UserInfo={_kCFNetworkCFStreamSSLErrorOriginalValue=-9824, kCFStreamPropertySSLPeerCertificates=(

"<cert(0x128850000) s: mss.cpc.getswish.net i: GeoTrust RSA CA 2018>",

"<cert(0x128850a00) s: GeoTrust RSA CA 2018 i: DigiCert Global Root CA>"

), _kCFStreamPropertySSLClientCertificateState=2, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x280a84f30>, _kCFStreamPropertySSLClientCertificates=(

"<SecIdentityRef: 0x2838a6b40>"

), _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9824}}, NSErrorClientCertificateChainKey=(

"<SecIdentityRef: 0x2838a6b40>"

), NSLocalizedDescription=An SSL error has occurred and a secure connection to the server cannot be made., NSErrorFailingURLKey=https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests, NSErrorFailingURLStringKey=https://mss.cpc.getswish.net/swish-cpcapi/api/v1/paymentrequests, NSErrorClientCertificateStateKey=2})


Edit: that's new for me, i didnt get the same output when i compared the output from yesterday.

Edit: that's new for me, i didnt get the same output when i compared the output from yesterday.


Are you sure you have not touched any parts of your code and settings? Or the server status may have changed.


I have no access to your certificate, so I cannot say anything sure, but I guess you are doing something wrong with your NSURLAuthenticationMethodClientCertificate response.

I recommend you to re-check it. Doesn't your server have sort of connection checking APIs?

I recommend you enable CFNetwork diagnostic logging (per QA1887) and see what that reports. That will let you see whether the problem is coming from CFNetwork or from the lower-level TLS code. It’s hard to say what’s what right now because the error from your first post indicates that CFNetwork might be involved (-1001 is

NSURLErrorTimedOut
), but the error from your second post indicates that there might be a TLS problem (error
errSSLPeerHandshakeFail
).

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

This is what result i got by using setenv("CFNETWORK_DIAGNOSTICS", "3", 1): https://pastebin.com/GcVJTw4z

I'm trying to use one certificate root ca wich name is DigiCert Global Root CA and the certificate has been listed: https://support.apple.com/en-us/HT208125


is there any difference when compare with a self signed certificate?

You’re CFNetwork diagnostic log clearly indicates that there’s a TLS error in play here (there’s no sign of

NSURLErrorTimedOut
in the log). As to what’s going on with TLS, it’s hard to say because the server requires that the client supply a certificate, and I don’t have such a certificate to test with.

Is there a test certificate available publicly? If not, my recommendation is that you open a DTS tech support incident so that we can continue this in private.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

let's do that in private, i have already send a DTS tech support request.

Cool. I’m on vacation this week but this will probably find it’s way to my queue when I get back in the office.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"