Parsing single parameter in path. #37
-
Hello! I'm using this great framework to handle deep link in my app! I'm wondering if there is a way to handle a url to generate a single string from it. Please see code below. enum AppRoute {
case book(id: String)
}
let appRouter = OneOf {
// GET /book/:id/xxx
Route(.case(AppRoute.book)) {
Path { "book"; Parse(.string); /* May be book name but we don't want to parse it */ }
}
}
let url = URL(string: "https://example.com/book/foo/bar")!
let result try appRouter.match(url: url) // expect to get AppRoute.book(id: "foo") If anyone have solution for this, it will be very grateful. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
@junjielu This is a surprisingly subtle problem, especially if you want to print the route back into a URL for the purpose of linking. E.g.: try appRouter.path(for: .book(id: "foo"))
// "/book/foo/???" What goes in that path component? If this is an important component of the route, it needs to also be in the data model: enum AppRoute {
case book(id: String, slug: String)
} Perhaps this path component is optional, where the segment is omitted when enum AppRoute {
case book(id: String, slug: String?)
// (42, "alice") -> "/book/42/alice"
// (42, nil) -> "/book/42"
} With this data model in place, there's no readymade API for this kind of thing (maybe there should be, but we'll have to think on it). You can, however, contort the existing APIs to first pluck off the known path components, and then insert a custom parser printer that does the work of grabbing the path component, if it exists, and then parsing/printing it: let router = Route(.case(AppRoute.book(id:slug:))) {
Path {
"books"
Int.parser()
}
AnyParserPrinter<URLRequestData, String?> { requestData in
requestData.path.isEmpty ? nil : String(requestData.path.removeFirst())
} print: { slug, input in
if let slug = slug {
input.path.prepend(slug[...])
}
}
} It's a bit gross, but will hopefully unblock you, and you could extract the any parser printer to a conformance where it doesn't stick out so much. Swift 5.7 come with some new result builder features that will hopefully allow us to simplify this in the future by reusing the Path {
"books"
Int.parser()
Optionally {
Parse(.string)
}
} But these features are of course limited to Swift 5.7, so we can't rely on them quite yet. |
Beta Was this translation helpful? Give feedback.
@junjielu This is a surprisingly subtle problem, especially if you want to print the route back into a URL for the purpose of linking. E.g.:
What goes in that path component? If this is an important component of the route, it needs to also be in the data model:
Perhaps this path component is optional, where the segment is omitted when
nil
:With this data model in place, there's no readymade API for this kind of thing (maybe there should be, but we…