Defining REST routes using warp

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.

1 Like

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 :sweat_smile:

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?

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.