There's already a Matcher approach in https://docs.rs/rama/latest/rama/http/service/web/index.html, in two ways:
match_service!
macro: this is same-same but using tuples and thus no need to Box. It is however a bit less easy to use for first time usersBoth are very flexible in that they allow you to match on pretty much anything. However for a traditional web server it is a lot nicer to work with a trie-like structure to match purely on paths. You could still mix-and-match that with the two approaches above in case you want to specialise further (e.g. method) once you are in a path. This is possible as the two above still result in a Service
(https://docs.rs/rama/latest/rama/trait.Service.html), which is also an EndpointService
(https://docs.rs/rama/latest/rama/http/service/web/trait.IntoEndpointService.html)
The Router
has to implement the Service
trait (https://docs.rs/rama/latest/rama/trait.Service.html), which will be very similar to how https://docs.rs/rama/latest/rama/http/service/web/struct.WebService.html#impl-Service%3CState,+Request%3CBody%3E%3E-for-WebService%3CState%3E does it, except that you would do it using an approach focussed on paths. These paths should support extraction of segment data and wildcards out of the box and inject them similar to how a PatchMatcher (https://docs.rs/rama/latest/rama/http/matcher/struct.PathMatcher.html) does it.
API interface could look like:
use rama::http::service::web::Router
let app = Router::new()
.get("/", root)
.get("/users", list_users)
.post("/users", create_user)
.get("/users/{id}", show_user)
.get("/assets/{*path}", serve_asset);
As part of implementing this Router
you can add matchit
as a dependency: https://docs.rs/matchit/latest/matchit/
You could also go fancier and create also some kind of RoutingService
which could wrap the WebService
and makes it a lot easier to chain based on common matchers such as methods etc, for same path. But that's more of an extra.
Which would allow you to make it look more like:
use rama::http::service::web::{Router, routing::get};
let app = Router::new()
.route("/", get(root))
.route("/users", get(list_users).post(create_user))
.route("/users", get(create_user))
.route("/users/{id}", get(show_user))
.route("/assets/{*path}", get(serve_asset));
Might be nicer and easier to implement, something to think about.
Pay now to fund the work behind this issue.
Get updates on progress being made.
Maintainer is rewarded once the issue is completed.
You're funding impactful open source efforts
You want to contribute to this effort
You want to get funding like this too