Thank you for bringing this up!
Is international domain support on the table? RFC 5890 / 5891, etc
as of today this code doesn't work:
let urlString = "https://www.ελ:443/public/?x=1"
let url = URL(string: urlString)!
and if you have the url string originally you have to first manually parse it into components, then feed components individually to URLComponent machinery to finally grab the resulting url:
let urlString = "https://www.ελ:443/public/?x=1"
// let url = URL(string: urlString)! // this doesn't work
// as a workaround:
// parse urlString manually, and derive scheme / host / port / path / query:
// let scheme = ... some function of urlString
// let host = ... some function of urlString
// let port = ... some function of urlString
// let path = ... some function of urlString
// let query = ... some function of urlString
var c = URLComponents()
c.scheme = scheme // https
c.host = host // "www.ελ"
c.port = port // 443
c.path = path // "/public/"
c.query = query // "x=1"
let url = c.url!
print(url) // "https://www.%CE%B5%CE%BB:443/public/?x=1"
print(url.host!) // "www.ελ"
This is nice and cool. Can you go one step further?
// After
let photoURL = baseURL.appending(paths: ["Photos", "\(id.first!)", id])
// After after
let photoURL = baseURL + "Photos" + id.first! + id
Using universal URL is double edge sword and leads a non type safe API. There are APIs that only accept file url and if you feed them http url you'll get a runtime error. Obviously it would be nicer if that was a compile time error. Example:
let webUrl = URL(string: "https://file-examples-com.github.io/uploads/2017/11/file_example_MP3_700KB.mp3")!
let player = try! AVAudioPlayer(contentsOf: webUrl)
// ?!?! [plugin] AddInstanceForFactory: No factory registered
// for id <CFUUID 0x6000031f85c0> F8BB1C28-BAE8-11D6-9C31-00039315CD46
I'd seriously consider splitting the two worlds, while still providing a way to support both type of resources for those APIs that can. And do this in a type safe manner.
URL caching is rather mysterious and not obvious. From the docs:
What if the cached resource changed since it was cached? Will the cache be properly invalidated? Does cache invalidation depend upon a particular way how the change is made?
Does that mean the cache is very very temporary and the cached entry will not be there on the next callout of event loop, say, some 0.01 seconds after resource was placed in cache?!?!