URLComponent does not accept IPv6 address as host in iOS 16

iOS 16 introduced "Internationalized Domain Name" support for URLComponent. As a result, URLComponent does not accept IPv6 address as host in iOS 16. Is this expected behaviour or a bug, and what would be the best workaround in this case?

// IPv4 URL
var ipv4URLComponents = URLComponents()
ipv4URLComponents.scheme = "https"
ipv4URLComponents.host = "66.94.29.13"
if let url = ipv4URLComponents.url {
    print("IPv4 URL:", url)
}

// IPv6 URL
var ipv6URLComponents = URLComponents()
ipv6URLComponents.scheme = "https"
ipv6URLComponents.host = "2001:0000:3238:dfe1:0063:0000:0000:fefb"
if let url = ipv6URLComponents.url {
    print("IPv6 URL:", url)
}

Output on iOS 15.5 device:

IPv4 URL: https://66.94.29.13
IPv6 URL: https://2001%3A0000%3A3238%3Adfe1%3A0063%3A0000%3A0000%3Afefb

Output on iOS 16 device:

IPv4 URL: https://66.94.29.13
IPv6 URL: https:

Related thread: https://developer.apple.com/forums/thread/709284

IMO this is a bug, on two separate axes:

  • It breaks existing code.

  • URL, and hence URLComponents, needs to be able to handle IPv6 addresses. Putting IP addresses in URLs is not something I like doing, but sometimes you just need to do it. And any place you support v4 you need to support v6 as a peer.

I’ve seen reports similar to this go by and I know that we’ve already made some fixes in this space. Are you testing this on the latest iOS 16 beta (16.0b4, 20A5328h)? If so, and the problem is present there, I encourage you to file a bug about this.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Thanks for the response. Yes, the problem persists on iOS 16.0b4 as well.

I submitted a bug - FB11287912

Apple engineer confirmed that this is the expected behaviour:

According to RFC 2732 Section 2, IPv6 addresses must be enclosed in [ and ] when it’s part of an URL. In this particular case, the host should be ipv6URLComponents.host = “[2001:0000:3238:dfe1:0063:0000:0000:fefb]”.

I can confirm that the suggested solution works in iOS 16. However, the problem is that it is only a workaround, since enclosing IPv6 address in [] does not work in iOS 15 and older. So I still need to use if #available(iOS 16.0, *) {} syntax if I want my code to work in both iOS 15 and 16.

I don't expect any updates regarding the issue. Just posting this in case someone with the same problem lands here.

Apple engineer confirmed that this is the expected behaviour

I disagree. While it is correct, that IPv6 addresses must be enclosed between [ and ] in URLs, the brackets are part of the URL syntax and not part of the host syntax. The host still is only 2001:0000:3238:dfe1:0063:0000:0000:fefb and not [2001:0000:3238:dfe1:0063:0000:0000:fefb]. The task of URLComponent is it to build an URL out of components or split an URL into components, and adding [ and ] for IPv6 is part of building the URL, just like removing them is part of splitting an URL. When I have to do that myself as a developer, I can as well do all URL building and parsing myself, what for would I then even need a class like URLComponent?

URLComponent does not accept IPv6 address as host in iOS 16
 
 
Q