Swift’s Foundation URL appears to have inconsistent behaviour when the host is longer than 63 characters depending on if the host has IDN escapable characters. If a host is pure ascii, URL will return with up to at least 256 characters present in the host section. If it contains a single emoji, URL will return nil if the IDN encoded string exceeds 63 characters.
I realise each section in a hostname is meant to be up to 63 octets (characters) (RFC1123), so I can understand that URL returns nil for IDN names, but I don't know why it then works for non-IDN.
I've tested this with identical results on Linux/FoundationEssentials via SwiftFiddle and Foundation on Version 26.0 (17A321)/Mac OS 26.0 (25A354).
Does anyone have any thoughts on this?
Example code
import Foundation
func letters(_ count: Int) -> String {
return String(repeating: "a", count: count)
}
func extraLetters(_ count: Int) -> String {
let face = "🧐" // = xn--9u9h
switch count {
case 8: return face
case 0...12: return letters(count)
case 13...36: return letters(count - 10) + face
default: return letters(count - 11) + face
}
}
func host(_ host: String) -> String {
return URL(string: "https://\(host)/")?.host(percentEncoded: false)
?? "<No URL>"
}
func printComparison(_ count: Int) {
let prefix = String(format: "%03d: ", count)
print("\(prefix)\(host(letters(count)))")
print("\(prefix)\(host(extraLetters(count)))")
}
for comparison in [8, 30, 63, 64, 128, 256] {
printComparison(comparison)
}
008: aaaaaaaa
008: xn--9u9h
030: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
030: xn--aaaaaaaaaaaaaaaaaaaa-uv13t
063: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
063: xn--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-r3017c
064: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
064: <No URL>
128: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
128: <No URL>
256: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
256: <No URL>