9 Replies
      Latest reply on Aug 3, 2018 2:12 PM by Heli_Guy
      Heli_Guy Level 1 Level 1 (0 points)

        The app I'm creating in Xcode 9 needs to load web page content, so I followed the code suggested in https://www.hackingwithswift.com/example-code/strings/how-to-load-a-string-from-a-website-url

         

            if let url = URL(string: "https://flightplanning.navcanada.ca/cgi-bin/Fore-obs/notam.cgi?ni_FIR=on&Stations=CZEG") {
            do {
                let contents = try String(contentsOf: url)
                print(contents)
            } catch {
                // contents could not be loaded
            }
        } else {
            // the URL was bad!
        }
        

         

        From various other threads, it seemed to be a problem with the info.plist file, so following these suggestions I added the following entries in the info.plist:

        https://i.stack.imgur.com/LYuv4.png

         

        <key>NSAppTransportSecurity</key>
        <dict>
          <key>NSAllowsArbitraryLoads</key>
          <false/>
          <key>NSExceptionDomains</key>
          <dict>
          <key>flightplanning.navcanada.ca</key>
          <dict/>
          <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
          <true/>
          <key>NSIncludesSubdomains</key>
          <true/>
          </dict>
        </dict>
        
        

         

        The errors returned:

        SSL_ERROR_SSL(1): operation failed within the library

        SSLV3_ALERT_HANDSHAKE_FAILURE:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/tls_record.c:547:SSL alert number 40

        HANDSHAKE_FAILURE_ON_CLIENT_HELLO

        Function boringssl_context_get_os_status: line 4268 SSL_AD_HANDSHAKE_FAILURE

        TIC TCP Conn Failed

        NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)

        Task <AB92C36B-6E8A-42E5-9C3E-73AF6E258F43>.<0> HTTP load failed (error code: -1200 [3:-9824])

        NSURLConnection finished with error - code -1200

         

        Any corrective suggestions would be greatly appreciated.

         

        Note when I use the same code to load web content from other web sites it seems to work ok.

        When I access this website, https://flightplanning.navcanada.ca/cgi-bin/Fore-obs/notam.cgi?ni_FIR=on&Stations=CZEG, on Safari, it loads the web site with no problems.

        • Re: Swift 4: Errors When Loading Web Page Content in iOS app
          Heli_Guy Level 1 Level 1 (0 points)

          Can anybody help?

          • Re: Swift 4: Errors When Loading Web Page Content in iOS app
            junkpile Level 6 Level 6 (2,375 points)

            Isn't it NSExceptionAllowsInsecureHTTPLoads (not NSTemporaryException...)?

             

            Does it work with the blanket NSAllowsArbitraryLoads set (and your exception domain removed / commented out)?

             

            Edit: Also, your syntax looks funky... line 8 should just be <dict> I think, to start the dictionary that contains the two keys (includes subdomains and allows arbitrary loads) for the exception domain. You should have three nested dictionaries: NSAppTransportSecurity, NSExceptionDomains, and the one for your exception domain.

              • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                Heli_Guy Level 1 Level 1 (0 points)

                No. Doesn’t work either. Same errors. Other web pages load ok and this specific web page loads on safari with no issues.

                  • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                    eskimo Apple Staff Apple Staff (9,845 points)

                    While this server supports HTTPS that support is quite out of date.  Specifically:

                    • It doesn’t support TLS 1.2.

                    • It doesn’t support forward secrecy.

                    I recommend that you work with the server folks to update it to support best practice security.

                    If that’s not possible then you will need to disable App Transport Security’s enforcement of best practice security by adding this to your Info.plist.

                    <key>NSAppTransportSecurity</key>
                    <dict>
                        <key>NSExceptionDomains</key>
                        <dict>
                            <key>flightplanning.navcanada.ca</key>
                            <dict>
                                <key>NSExceptionMinimumTLSVersion</key>
                                <string>TLSv1.0</string>
                                <key>NSExceptionRequiresForwardSecrecy</key>
                                <false/>
                            </dict>
                        </dict>
                    </dict>

                    Share and Enjoy

                    Quinn “The Eskimo!”
                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                    let myEmail = "eskimo" + "1" + "@apple.com"

                      • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                        Heli_Guy Level 1 Level 1 (0 points)

                        Hello,

                        Thank you for your reply. I was really eager to try this out but unfortunately, have been on the road.

                         

                        I tried it today. But still get errors upon attempting to load the web page contents:

                        2018-07-21 18:06:21.451622-0400 Load Web Content[7033:2216088] [BoringSSL] Function boringssl_session_errorlog: line 2866 [boringssl_session_handshake_continue] SSL_ERROR_SSL(1): operation failed within the library
                        2018-07-21 18:06:21.451965-0400 Load Web Content[7033:2216088] [BoringSSL] Function boringssl_session_handshake_error_print: line 2805 boringssl ctx 0x7f9daf4052e0: 140315314882832:error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/tls_record.c:547:SSL alert number 40
                        2018-07-21 18:06:21.452278-0400 Load Web Content[7033:2216088] [BoringSSL] Function boringssl_session_handshake_error_print: line 2805 boringssl ctx 0x7f9daf4052e0: 140315314882832:error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/handshake_client.c:946:
                        2018-07-21 18:06:21.452520-0400 Load Web Content[7033:2216088] [BoringSSL] Function boringssl_context_get_os_status: line 4268 SSL_AD_HANDSHAKE_FAILURE
                        2018-07-21 18:06:21.460732-0400 Load Web Content[7033:2216088] TIC TCP Conn Failed [1:0x60000017d040]: 3:-9824 Err(-9824)
                        2018-07-21 18:06:21.461300-0400 Load Web Content[7033:2216088] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
                        2018-07-21 18:06:21.461409-0400 Load Web Content[7033:2216088] Task <59B7AE65-5FCA-407F-BDE1-0914AD9D350D>.<0> HTTP load failed (error code: -1200 [3:-9824])
                        2018-07-21 18:06:21.461551-0400 Load Web Content[7033:2216091] NSURLConnection finished with error - code -1200
                        

                        If you please have any other suggestions I would greatly appreciate it as I'm stuck and can't progress with my app without this.

                         

                        Here is the code in my test app:

                            override func viewDidLoad()
                            {
                                super.viewDidLoad()
                                // Do any additional setup after loading the view, typically from a nib.
                                
                                if let url = URL(string: "https://flightplanning.navcanada.ca/cgi-bin/Fore-obs/notam.cgi?ni_FIR=on&Stations=CZEG")
                                {
                                    do
                                    {
                                        let contents = try String(contentsOf: url)
                                        print(contents)
                                    }
                                    catch
                                    {
                                        // contents could not be loaded
                                    }
                                }
                                else
                                {
                                    // the URL was bad!
                                }
                            }
                        
                        
                        

                         

                        Here is the info.plist

                         <?xml version="1.0" encoding="UTF-8"?>
                        <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
                        <plist version="1.0">
                        <dict>
                          <key>CFBundleDevelopmentRegion</key>
                          <string>$(DEVELOPMENT_LANGUAGE)</string>
                          <key>CFBundleExecutable</key>
                          <string>$(EXECUTABLE_NAME)</string>
                          <key>CFBundleIdentifier</key>
                          <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
                          <key>CFBundleInfoDictionaryVersion</key>
                          <string>6.0</string>
                          <key>CFBundleName</key>
                          <string>$(PRODUCT_NAME)</string>
                          <key>CFBundlePackageType</key>
                          <string>BNDL</string>
                          <key>CFBundleShortVersionString</key>
                          <string>1.0</string>
                          <key>CFBundleVersion</key>
                          <string>1</string>
                        
                        
                          <key>NSAppTransportSecurity</key>  
                          <dict>  
                             <key>NSExceptionDomains</key>  
                             <dict>  
                          <key>flightplanning.navcanada.ca</key>  
                          <dict>  
                             <key>NSExceptionMinimumTLSVersion</key>  
                             <string>TLSv1.0</string>  
                             <key>NSExceptionRequiresForwardSecrecy</key>  
                             <false/>  
                          </dict>  
                             </dict>  
                          </dict>  
                        
                        
                        </dict>
                        </plist>
                         
                          • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                            eskimo Apple Staff Apple Staff (9,845 points)

                            I put your code into a test project here and then tweaked the catch clause to print the error:

                            NSLog("error %@", error as NSError)

                            Here’s what I see:

                            2018-07-23 10:36:18.485751+0100 xxsi[3066:315833] error Error Domain=NSCocoaErrorDomain Code=264 "The file “notam.cgi” couldn’t be opened because the text encoding of its contents can’t be determined." UserInfo={NSURL=https://flightplanning.navcanada.ca/cgi-bin/Fore-obs/notam.cgi?ni_FIR=on&Stations=CZEG}

                            So the problem isn’t that you can’t load the resource, it’s that the resource isn’t being parsed correctly.  That’s because of a text encoding problem; you’re using String(contentsOf:), whose text encoding behaviour is not well specified.

                            I strongly recommend that you fetch the resource using URLSession.  For example, code like this:

                            let url = URL(string: "https://flightplanning.navcanada.ca/cgi-bin/Fore-obs/notam.cgi?ni_FIR=on&Stations=CZEG")!
                            let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
                            URLSession.shared.dataTask(with: request) { (data, response, error) in
                                if let error = error as NSError? {
                                    NSLog("task transport error %@ / %d", error.domain, error.code)
                                    return
                                }
                                let response = response as! HTTPURLResponse
                                let data = data!
                                NSLog("task finished with status %d, bytes %d", response.statusCode, data.count)
                            }.resume()

                            prints:

                            2018-07-23 10:38:25.422562+0100 xxsi[3066:318977] task finished with status 200, bytes 27935

                            indicating that the resource was fetched correctly.  Moreover, the content type (response?.mimeType) is text/html, meaning that you need to parse the data as HTML, and HTML has its own rules about how to deal with text encodings.

                            Now, if you only care about this specific site, and you’re OK with your code breaking if the site changes its text encoding, you can take a shortcut and interpret the data as ISO-8859-1 (aka ISO-Latin-1).  For example:

                            if let text = String(data: data, encoding: .isoLatin1) {
                                … deal with `text` …
                            } else {
                                … `data` wasn't parseable as ISO-Latin-1 …
                            }

                            Share and Enjoy

                            Quinn “The Eskimo!”
                            Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                            let myEmail = "eskimo" + "1" + "@apple.com"

                              • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                                Heli_Guy Level 1 Level 1 (0 points)

                                Hello,

                                I really apreciate your assistance. But I tried your version of the code, it seems to have the same issue:

                                 

                                I tried your version of the code:

                                    override func viewDidLoad()
                                    {
                                        super.viewDidLoad()
                                        // Do any additional setup after loading the view, typically from a nib.
                                
                                        let url = URL(string: "https://flightplanning.navcanada.ca/cgi-bin/Fore-obs/notam.cgi?ni_FIR=on&Stations=CZEG")!
                                        let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
                                        URLSession.shared.dataTask(with: request)
                                        { (data, response, error) in
                                            if let error = error as NSError?
                                            {
                                                NSLog("--------------------------------------------------------")
                                                NSLog("task transport error %@ / %d", error.domain, error.code)
                                                NSLog("--------------------------------------------------------")
                                
                                                print("--------------------------------------------------------")
                                                print("task transport error \(error.domain) / \(error.code)")
                                                print("--------------------------------------------------------")
                                                return
                                            }
                                            let response = response as! HTTPURLResponse
                                            let data = data!
                                            NSLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                                            NSLog("task finished with status %d, bytes %d", response.statusCode, data.count)
                                            NSLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                                            
                                            print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                                            print("task finished with status \(response.statusCode), \(data.count) bytes")
                                            print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
                                
                                        }.resume()
                                    }
                                
                                

                                 

                                And this is what I see in the output:

                                2018-07-23 09:42:02.319798-0400 Load Web Content[23874:4065599] [BoringSSL] Function boringssl_session_errorlog: line 2866 [boringssl_session_handshake_continue] SSL_ERROR_SSL(1): operation failed within the library
                                2018-07-23 09:42:02.320099-0400 Load Web Content[23874:4065599] [BoringSSL] Function boringssl_session_handshake_error_print: line 2805 boringssl ctx 0x7f91a6602b00: 140263629523344:error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/tls_record.c:547:SSL alert number 40
                                2018-07-23 09:42:02.321107-0400 Load Web Content[23874:4065599] [BoringSSL] Function boringssl_session_handshake_error_print: line 2805 boringssl ctx 0x7f91a6602b00: 140263629523344:error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/handshake_client.c:946:
                                2018-07-23 09:42:02.321615-0400 Load Web Content[23874:4065599] [BoringSSL] Function boringssl_context_get_os_status: line 4268 SSL_AD_HANDSHAKE_FAILURE
                                2018-07-23 09:42:02.333874-0400 Load Web Content[23874:4065599] TIC TCP Conn Failed [1:0x600000173200]: 3:-9824 Err(-9824)
                                2018-07-23 09:42:02.336214-0400 Load Web Content[23874:4065599] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
                                2018-07-23 09:42:02.336707-0400 Load Web Content[23874:4065599] Task .<1> HTTP load failed (error code: -1200 [3:-9824])
                                2018-07-23 09:42:02.337733-0400 Load Web Content[23874:4065596] Task .<1> finished with error - code: -1200
                                2018-07-23 09:42:02.388090-0400 Load Web Content[23874:4065599] --------------------------------------------------------
                                2018-07-23 09:42:02.389397-0400 Load Web Content[23874:4065599] task transport error NSURLErrorDomain / -1200
                                2018-07-23 09:42:02.389590-0400 Load Web Content[23874:4065599] --------------------------------------------------------
                                --------------------------------------------------------
                                task transpor error NSURLErrorDomain / -1200
                                --------------------------------------------------------
                                
                                

                                Does this code work differently on your end?

                                 

                                Thank you.

                                  • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                                    eskimo Apple Staff Apple Staff (9,845 points)

                                    Hmmm, I’m not sure why this isn’t working for you.  Here’s what I did:

                                    1. In Xcode 9.4, I created a new project from the iOS > Single View Application template.

                                    2. I replaced the viewDidLoad method implementation with the code you posted yesterday (23 Jul).

                                    3. I editing the Info.plist to add the ATS exception properties you posted on 21 Jul.

                                    4. I built and ran the app on an iOS 11.4 simulator.

                                    5. It printed:

                                      2018-07-24 08:59:57.056802+0100 xxsi9[2090:174383] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                      2018-07-24 08:59:57.061785+0100 xxsi9[2090:174383] task finished with status 200, bytes 27625
                                      2018-07-24 08:59:57.061950+0100 xxsi9[2090:174383] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                      task finished with status 200, 27625 bytes
                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

                                      .

                                    Please repeat those steps to see if you can get it working.  If not, I recommend you open a DTS tech support incident so I can help you on a one-on-one basis.

                                    Share and Enjoy

                                    Quinn “The Eskimo!”
                                    Apple Developer Relations, Developer Technical Support, Core OS/Hardware
                                    let myEmail = "eskimo" + "1" + "@apple.com"

                                      • Re: Swift 4: Errors When Loading Web Page Content in iOS app
                                        Heli_Guy Level 1 Level 1 (0 points)

                                        Hello,

                                        I really appreciate your patience and support.

                                        I repeated steps 1 through 5 as in your last post but the problem presists.

                                         

                                        See screenshots: https://imgur.com/a/sPLd9kU

                                         

                                        But same type of errors persist:

                                        2018-08-03 16:02:24.674881-0500 Load Web Data 2[14178:4237199] [BoringSSL] Function boringssl_session_errorlog: line 2866 [boringssl_session_handshake_continue] SSL_ERROR_SSL(1): operation failed within the library
                                        2018-08-03 16:02:24.676030-0500 Load Web Data 2[14178:4237199] [BoringSSL] Function boringssl_session_handshake_error_print: line 2805 boringssl ctx 0x7ff2b7604ce0: 140680525515408:error:10000410:SSL routines:OPENSSL_internal:SSLV3_ALERT_HANDSHAKE_FAILURE:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/tls_record.c:547:SSL alert number 40
                                        2018-08-03 16:02:24.676634-0500 Load Web Data 2[14178:4237199] [BoringSSL] Function boringssl_session_handshake_error_print: line 2805 boringssl ctx 0x7ff2b7604ce0: 140680525515408:error:1000009a:SSL routines:OPENSSL_internal:HANDSHAKE_FAILURE_ON_CLIENT_HELLO:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.50.14/ssl/handshake_client.c:946:
                                        2018-08-03 16:02:24.677310-0500 Load Web Data 2[14178:4237199] [BoringSSL] Function boringssl_context_get_os_status: line 4268 SSL_AD_HANDSHAKE_FAILURE
                                        2018-08-03 16:02:24.688796-0500 Load Web Data 2[14178:4237199] TIC TCP Conn Failed [1:0x60800017b540]: 3:-9824 Err(-9824)
                                        2018-08-03 16:02:24.690940-0500 Load Web Data 2[14178:4237199] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)
                                        2018-08-03 16:02:24.691086-0500 Load Web Data 2[14178:4237199] Task <9C8D168A-4E67-42CB-BDE7-BFDAD5A4DAED>.<1> HTTP load failed (error code: -1200 [3:-9824])
                                        2018-08-03 16:02:24.692087-0500 Load Web Data 2[14178:4237212] Task <9C8D168A-4E67-42CB-BDE7-BFDAD5A4DAED>.<1> finished with error - code: -1200
                                        2018-08-03 16:02:24.757671-0500 Load Web Data 2[14178:4237199] --------------------------------------------------------
                                        2018-08-03 16:02:24.761062-0500 Load Web Data 2[14178:4237199] task transport error NSURLErrorDomain / -1200
                                        2018-08-03 16:02:24.761175-0500 Load Web Data 2[14178:4237199] --------------------------------------------------------
                                        --------------------------------------------------------
                                        task transport error NSURLErrorDomain / -1200
                                        --------------------------------------------------------
                                        

                                         

                                         

                                        I'll follow the DTS Tech Support link you suggested.

                                        Thanks.