0

I'm trying to use Swift's NSURLRequest and NSURLConnection to communicate with the Riot Games (League of Legends) API. I seem to be having issues not only with Riot URLs but with all HTTPS URLs.

I have the following code in a Swift Playground:

func doGET(url: String) {
  if let urlhandle = NSURL(string: url) {
    var request = NSURLRequest(URL: urlhandle)

    var response: NSURLResponse?
    var error: NSErrorPointer = nil
    var data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: error)
    println("\n\(url)\n")
    println("\(response)\n\n")
  } else {
    println("Bad URL: \(url)")
  }
}

doGET("http://google.com")

doGET("https://na.api.pvp.net/api/lol/na/v1.2/champion/1?api_key=\(apikey)")

doGET("https://google.com")

I'm getting the following errors/output:

http://google.com

Optional(<NSHTTPURLResponse: 0x7fcff2443d60> { URL: http://www.google.com/ } { status code: 200, headers {
"Accept-Ranges" = none;
"Alternate-Protocol" = "80:quic,p=0.08";
"Cache-Control" = "private, max-age=0";
"Content-Type" = "text/html; charset=ISO-8859-1";
Date = "Wed, 25 Feb 2015 23:13:45 GMT";
Expires = "-1";
Server = gws;
"Transfer-Encoding" = Identity;
Vary = "Accept-Encoding";
"X-Frame-Options" = SAMEORIGIN;
"X-XSS-Protection" = "1; mode=block";
} })


2015-02-25 16:13:45.357 URL Requests[36397:3779864] NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9807)

https://na.api.pvp.net/api/lol/na/v1.2/champion/1?api_key=<redacted>

nil


2015-02-25 16:13:45.402 URL Requests[36397:3779864] NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9807)

https://google.com

nil

As you can see, the request succeeds on HTTP URLs but fails on secure HTTPS URLs. How can I allow the use of HTTPS?

Scott Odle
  • 290
  • 1
  • 2
  • 16

3 Answers3

1

It will probably not solve the https problem but you should always use stringByAddingPercentEscapesUsingEncoding before converting your links to NSURL

"http://google.com".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!

"https://na.api.pvp.net/api/lol/na/v1.2/champion/1?api_key=any key".stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! // "https://na.api.pvp.net/api/lol/na/v1.2/champion/1?api_key=any%20key"


func doGET(link: String) {
  if let url = NSURL(string: link.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!) {
    var response: NSURLResponse?
    var error: NSErrorPointer = nil
    let data = NSURLConnection.sendSynchronousRequest(NSURLRequest(URL: url), returningResponse: &response, error: error)
    println("\n\(url)\n")
    println("\(response)\n\n")
  } else {
    println("Bad URL")
  }
}
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • Turns out it's an issue with Xcode and not my code. It runs fine from the Swift CLI, but Xcode is firewalled or something. – Scott Odle Feb 26 '15 at 04:24
  • The most important thing is just to make sure the link conforms to NSURL so don't forget to use it before converting to NSURL – Leo Dabus Feb 26 '15 at 04:25
  • Right, I have `urlhandle = NSURL(string: url.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)` – Scott Odle Feb 26 '15 at 04:26
1

Your code should work in a 'normal' environment. But as you mentioned that you are in the university, there might be an issue in accepting the server certificates. So I would recommend you to add the NSURLConnectionDelegate and add the following two methods. I've got the idea from Gordon's answer here.

func connection(connection: NSURLConnection, canAuthenticateAgainstProtectionSpace protectionSpace: NSURLProtectionSpace) -> Bool {
    return protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust
}

func connection(connection: NSURLConnection, didReceiveAuthenticationChallenge challenge: NSURLAuthenticationChallenge) {
    challenge.sender.useCredential(NSURLCredential(forTrust: challenge.protectionSpace.serverTrust), forAuthenticationChallenge: challenge)
}

The case in the question mentioned is another, but I think you've got the same problem with the server certificates.

Community
  • 1
  • 1
Christian
  • 22,585
  • 9
  • 80
  • 106
  • Where would I put this delegate code, and would it cause my app to fail App Store approval if I use it? – Scott Odle Feb 26 '15 at 00:28
  • No it won't. You can put it inside your viewcontroller. Have you tried doing it without the riot-url? So only the http and https of google.com. – Christian Feb 26 '15 at 00:29
  • I've tried it on both my home and University WiFi with and without the Riot URL, so it's not a network issue. – Scott Odle Feb 26 '15 at 00:47
  • I've tried it in my playground and in a project. It worked. I would recommend that you try it with a 3G network. – Christian Feb 26 '15 at 00:48
  • Just tried using a T-Mobile 4G hotspot (without your delegate). Still fails. – Scott Odle Feb 26 '15 at 00:52
  • There has to be a problem somewhere else in your code. I would debug and check where the error occurs. – Christian Feb 26 '15 at 00:54
  • There is nowhere else in my code. I have only a Playground with the code I posted. – Scott Odle Feb 26 '15 at 01:23
  • 1
    Thank you for your answer, and sorry if I was a little hostile. Turns out it's an issue with Xcode and not my code. It runs fine from the Swift CLI. – Scott Odle Feb 26 '15 at 04:20
0

Thanks @Christian and @Leonardo. It appears to be a firewall/certificate problem on my own machine. The existing code runs perfectly from the command prompt (swift /path/to/file), it only fails in Xcode. I'd like to eventually have it working in Xcode, but I'll cross that bridge when I come to it.

Scott Odle
  • 290
  • 1
  • 2
  • 16