swift-url-routing
swift-url-routing copied to clipboard
Ignoring path components
Hello everyone 👋
We are currently using URLRouting in our Application. In our current case we've been facing a problem with the parsing of the path of an URL.
Use case:
The link which will be parsed looks like this: https://example.de/colors
In some cases this link can have multiple path components. The number of path components is not fixed and we do not know how many additional path components are added to this link (0..n).
- https://example.de/colors/foo
- https://example.de/colors/foo/bar
Is there any way this can be done. We tried multiple combinations with Skip, Many and Rest but the problem seems to be that the Path component passes one element to the Parser at a time.
The workaround for us would be to implement a custom Path parser which does not pass the path components one by one but the whole path at once. So we can work with the Prefix Parser. We'd like to know if there is a better way with the given component?
Thank you for having a look at this. 👍
Following a code example to represent the problem.
import Foundation
import URLRouting
enum AppRoute {
case colors
}
let appRouter = OneOf {
Route(.case(AppRoute.colors)) {
Scheme("https")
Host("example.de")
Path {
"colors"
}
}
}
let testURL = URL(string: "https://example.de/colors")!
let testURL2 = URL(string: "https://example.de/colors/foo")!
try appRouter.match(url: testURL) // matches AppRoute.colors
try appRouter.match(url: testURL2) // fails with expected end of input`
I am also having this issue. Did you manage to get this working in the end?
Unfortunately not with the given Parsers. For me the solution as to write a customer parser which checks for the prefix only and consumes the path.
struct PrefixPath: ParserPrinter {
@usableFromInline
var pathPrefix: String
/// Initializes a prefix path parser.
/// Validates if a given path starts with the prefix. Path after the prefix will be ignored.
/// - Parameter pathPrefix: The prefix which will be
@inlinable
init(_ pathPrefix: String) {
self.pathPrefix = pathPrefix
}
@inlinable
func parse(_ input: inout URLRequestData) throws {
guard input.path.count >= 1 else { throw PrefixPathRoutingError() }
let path = input.path.joined(separator: "/").lowercased()
guard path.hasPrefix(pathPrefix.lowercased()) else {
throw PrefixPathRoutingError()
}
input.path = []
}
@inlinable
func print(_: (), into input: inout URLRequestData) {
input.path = pathPrefix.split(separator: "/")[...]
}
}
@usableFromInline
struct PrefixPathRoutingError: Error {
@usableFromInline
init() {}
}