The first error is:
--> src/main.rs:58:14
|
58 | .and(with_state(state))
| ^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `impl warp::Filter`
You can fix this by adding a Clone
bound to the return type of with_state
(matching the bounds on with_db
):
- fn with_state(state: State) -> impl Filter<Extract = (State,), Error = Infallible> {
+ fn with_state(state: State) -> impl Filter<Extract = (State,), Error = Infallible> + Clone {
Then you'll get an error that your closures expect the wrong type, which you can fix like this:
- .map(|dog_map: DogMap| {
+ .map(|dog_map: State| {
Then there's a problem caused by returning a Rejection
to map
. You can fix that by using and_then
instead of map
. This will also require you to use an async
block or function, which is good because you need it to access your tokio::sync::Mutex
:
let get_dog = warp::path!("dog" / String)
.and(warp::get())
.and(with_state(state.clone()))
.and_then(|id, dog_map: State| async move {
println!("got get for id {}, dog_map = {:?}", id, dog_map);
if let Some(dog) = dog_map.lock().await.get(&id) {
Ok(warp::reply::json(&dog))
} else {
Err(warp::reject::not_found())
}
});
Then, for routes that never return an error, you'll get an error that the compiler can't infer the error type. Until we have proper async closures, the easiest way to annotate the return type is to change the closure to an async fn
like in the todos.rs
example:
let get_dogs = warp::path!("dog")
.and(warp::get())
.and(with_state(state.clone()))
.and_then(handle_get_dogs);
async fn handle_get_dogs(dog_map: State) -> Result<Json, Rejection> {
println!("got get: dog_map = {:?}", dog_map);
let dogs: Vec<Dog> = dog_map.lock().await.values().cloned().collect();
Ok(warp::reply::json(&dogs))
}