Remove `scheme` requirement
My app supports routing with multiple schemes (eg. myapp://, othertarget:// & https://), and I would like for the same URLOpenHandler to be called, no matter the scheme. I'm trying to migrate from JLRoutes (which can handle this), and coming up against the roadblock of the "Either matcher or URL should have scheme: '\(url)'" assertion in URLMatcher.
The way I would have assumed, and hoped, it would work is that if no scheme is provided when building the map, it is assumed to be a universal route and is matched no-matter the input URL's scheme (but if a scheme is provided in the map pattern, or the scheme property is set on URLNavigator, it is only matched when that scheme is input).
I understand that this would change expected behaviour for people already using the framework, but think it'd be a great addition to the project.
In the meantime, or if you dont feel it fits the goals of your work, do you have any suggestions as to how best to solve this problem otherwise? I guess mutating the input-URL's scheme to always be a primary scheme just before it is passed to the open(url:) method might work, but seems rather hacky.
Thanks!
FYI, an implementation of the hacky solution I described at the bottom could look something like this:
extension URLNavigator {
func initialize() {
self.scheme = "myapp"
self.map("/users/<userId>") { (url, values) -> Bool in
// ... do stuff
print(url, values)
return true
}
}
/// open the url, but first tries to apply the shared `scheme` to the url before matching
func openNormalizedURL(_ url:URL) -> Bool {
var components = URLComponents(url: url, resolvingAgainstBaseURL: true)
components?.scheme = self.scheme
if let normalizedSchemeURL = components?.url {
return Navigator.open(normalizedSchemeURL)
} else {
return Navigator.open(url)
}
}
}
// eg. the following all hit the same `URLOpenHandler`
Navigator.initialize()
Navigator.openNormalizedURL(URL(string:"//users/abc123")!)
Navigator.openNormalizedURL(URL(string:"https://users/abc123")!)
Navigator.openNormalizedURL(URL(string:"myapp://users/abc123")!)
Navigator.openNormalizedURL(URL(string:"foo://users/abc123")!)
Can you share the code that caused an error? I think this might work.
Navigator.map("myapp://users/<id>", handler)
Navigator.map("othertarget://users/<id>", handler)
Navigator.map("https://users/<id>", handler)
For example:
Navigator.map("/users/<id>", handler)
// then later:
Navigator.open("myapp://users/abc123")
The issue is that a scheme is required to have been set (either with scheme property, or in the map(:) method) before any open calls are made. I was hoping for a situation where scheme can just be ignored completely, so it doesnt matter what scheme is passed to open().
Hmm, I'm not sure that I completely understood. Is this what you want to do? For example:
Navigator.map("*://users/<id>", handler) // map wildcard scheme
Then the following open() executes same handler even if the anyscheme and hello is not registered? 🤔
Navigator.open("anyscheme://users/123")
Navigator.open("hello://users/123")
Navigator.open("world://users/123")
Kind of, but without the need for the wildcard. I think the closest to what i'm talking is about is how JLRoutes handles it... this seems like a very flexible solution - see the Schemes section of their readme: https://github.com/joeldev/JLRoutes
This is not supported yet. Maybe I can consider to add this feature on next major update but currently I don't think this is necessary for general purpose.