I would like to create a warp path segment filter from a path that is passed in via configuration. I've not been able to figure out how to make it work yet. I've tried to split the path string, then assemble a path filter by using the iterator methods. However, I've not been able to make heads or tails of the type errors there.
I would like to be able to do this:
// This will be dynamically given as a command line argument or loaded from a file.
let config_provided_path = "/foo/bar/baz";
let route1 = warp::get().and(warp::path("cow")).map(|| "Goes moo, moo!");
let route2 = warp::get().and(warp::path("dog")).map(|| "Goes woof, woof!");
let route3 = warp::get().and(warp::path("cat")).map(|| "Goes meow!");
let routes = warp::path(config_provided_path).and(route1.or(route2).or(route3));
warp::serve(routes).run(bind_address).await;
What's the desired outcome? Are you trying to have that config path available to the filters (ie available to the map functions in the example)? Or are you just trying to serve files from those folders?
Ahh. So here's one way to do it that's not the most efficient but it works. The trick that i used was to use boxed() which basically hides the type behind a pointer. Otherwise every call to and(..) creates a new type which wraps the previous one which leads to issues and a series of potentially difficult error messages to follow. warp doesn't expose a bunch of its internals, so i don't immediately see a simple solution that's more efficient.
let bind_address: std::net::SocketAddrV4 = "127.0.0.1:8000".parse().unwrap();
// This will be dynamically given as a command line argument or loaded from a file.
let config_provided_path = "/foo/bar/baz";
let base = config_provided_path
.split('/')
.skip_while(|p| p.is_empty())
.fold(warp::any().boxed(), |f, path| {
f.and(warp::path(path)).boxed()
});
let route1 = warp::get().and(warp::path("cow")).map(|| "Goes moo, moo!");
let route2 = warp::get()
.and(warp::path("dog"))
.map(|| "Goes woof, woof!");
let route3 = warp::get().and(warp::path("cat")).map(|| "Goes meow!");
let routes = base.and(route1.or(route2).or(route3));
warp::serve(routes).run(bind_address).await;