How can I implement a GET route that can return a 404 status?
Here is my attempt: rust-warp-demo/main.rs at master · mvolkmann/rust-warp-demo · GitHub
The error is "match
arms have incompatible types" and "expected struct Json
, found struct Rejection
". I understand what it is saying, but I don't know the proper way to fix it in the context of using warp. It seems like being able to define routes that can return a "reply" or a "reject" is exactly what I want. Maybe there is a type I haven't discovered yet that can encompass both of those.
I don't know warp, but after staring at the docs for a while, I think that you can't use the rejection thing in map
, but instead need to return some sort of impl Reply
. Once you have found an impl Reply
for the error path, I believe you can call into_response
on either to turn them into the same type.
So I think something like this should do it:
let get_dog = warp::path!("dog" / String).map(move |id: String| {
match dog_map.read().get(&id) {
Some(dog) => warp::reply::json(dog).into_response(),
None => warp::reply::with_status("not found", StatusCode::from_u16(404)).into_response(),
}
});
To be clear, I have no idea whether this is idiomatic.
I think it would be more idomatic to use and_then
like so:
let get_dog = warp::path!("dog" / String).and_then(move |id: String| async move {
warp::reply::json(dog_map.read().get(&id).ok_or_else(warp::reject::not_found)?)
});
Constructing ad-hoc errror pages is generally discouraged in Warp, using the rejection system is better.
The compiler doesn't like the use of ?
there. It says "the ?
operator can only be used in a closure that returns Result
or Option
(or another type that implements Try
)"
Oh, you'll have to wrap it in Ok
, I forgot to do that
Do you mean like this? This gives me a different error.
warp::reply::json(dog_map.read().get(&id).ok_or_else(Ok(warp::reject::not_found)))
I meant like this:
let get_dog = warp::path!("dog" / String).and_then(move |id: String| async move {
Ok(warp::reply::json(dog_map.read().get(&id).ok_or_else(warp::reject::not_found)?))
});
So that the return type is a Result.
With that change I get the error "?
couldn't convert the error to warp::http::Error
"
and "the trait From<Rejection>
is not implemented for warp::http::Error
".
Shouldn't it return an Err
value when the dog is not found?