Reputation: 6362
I'm using warp to create a server in Rust. And let's say I have these two routes setup.
let route_one = warp::get().and(warp::path("path1")).map(|| warp::reply());
let route_two = warp::get().and(warp::path("path2")).map(|| warp::reply());
warp::serve(route_one.or(route_two))
.run(([127, 0, 0, 1], 3000))
.await;
I would like to move the routes into their own function. What would the return type be?
For instance:
async fn get_route_one() {
warp::get().and(warp::path("path1")).map(|| warp::reply())
}
async fn get_route_two() {
warp::get().and(warp::path("path1")).map(|| warp::reply())
}
#[tokio::main]
async fn main() {
warp::serve(get_route_one().or(get_route_two()))
.run(([127, 0, 0, 1], 3000))
.await;
}
I've tried using warp:Filter
and multiple variations of it, but I haven't found a return type that compiles.
P.S. I know in this example extracting out the filters into their own functions just complicates things, but I have a situation where it may actually simplify things.
Upvotes: 3
Views: 2448
Reputation: 3169
The following code worked for me -- both your example and my more complex use case. (The other answers were helpful as a starting point, but didn't resolve my issues).
The way I got it to work was by removing async
since we don't need function to be async just to generate a filter and it works around the fact that Rust compiler is a little finicky these days for use cases like these:
use warp::Filter;
fn get_route_one()
-> impl Filter<Extract = (impl warp::Reply + 'static,), Error = warp::Rejection> + Clone + 'static {
warp::get().and(warp::path("path1")).map(|| warp::reply())
}
fn get_route_two()
-> impl Filter<Extract = (impl warp::Reply + 'static,), Error = warp::Rejection> + Clone + 'static {
warp::get().and(warp::path("path1")).map(|| warp::reply())
}
#[tokio::main]
async fn main() {
warp::serve(get_route_one().or(get_route_two()))
.run(([127, 0, 0, 1], 3000))
.await;
}
Upvotes: 0
Reputation: 7835
This is what we do in our own projects. For instance, we may have an endpoint like this:
pub async fn index(cfg: crate::settings::Settings) -> Result<impl warp::Reply, warp::Rejection> {
info!("Index endpoint called");
Ok(warp::reply::with_status(
format!("Welcome to Our API Version {}", cfg.version),
http::StatusCode::OK,
))
}
And we may have another endpoint like this:
pub async fn health() -> Result<impl warp::Reply, warp::Rejection> {
Ok(warp::reply::with_status("OK", http::StatusCode::OK))
}
We can build a function that wraps these up like this:
use warp::Filter;
/// External endpoints: /v1/base
pub fn base_endpoints(
config: crate::settings::Settings,
) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
let base_endpoints_trunk = warp::path("v1").and(warp::path("base"));
let index = base_endpoints_trunk
.and(warp::get())
.and(warp::path::end())
.and(crate::settings::with_cfg(config.clone()))
.and_then(index);
let health = base_endpoints_trunk
.and(warp::get())
.and(warp::path("health"))
.and(warp::path::end())
.and_then(health);
index.or(health)
}
Then, inside our main
, we can do something like this:
let base = endpoints::base_endpoints(CONFIG.clone());
warp::serve(base.recover(errors::handle_rejection)).run(([0, 0, 0, 0], 9000)).await
Upvotes: 2
Reputation: 6651
It'll depend on your actual types but something in the vicinity of impl Filter<Extract = impl warp::Reply, Error = warp::Rejection>
. I'll recommend to check out the todos example for inspiration.
Upvotes: 2