Warp: the trait `Reply` is not implemented

Hello folks,

I'm having a play with the warp library as a possible solution for building RESTful APIs. Here's a little mini code snippet that shows the kind of thing I'm trying to do:

use warp::Filter;

fn get_hello(name: String) -> std::result::Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::with_status(
        format!("Hello {}\n", name),
        http::StatusCode::OK
    ))
}

#[tokio::main]
async fn main() {
    let routes = warp::get()
        .and(warp::path("hello"))
        .and(warp::path::param())
        .map(get_hello);

    warp::serve(routes)
        .run(([127, 0, 0, 1], 3030))
        .await;
}

If I try to build/run this I get the following compiler error:

error[E0277]: the trait bound `Result<impl Reply, Rejection>: Reply` is not satisfied
  --> src/main.rs:20:5
   |
20 |     warp::serve(routes)
   |     ^^^^^^^^^^^ the trait `Reply` is not implemented for `Result<impl Reply, Rejection>`
   |
   = help: the following implementations were found:
             <Result<T, http::Error> as Reply>
   = note: required because of the requirements on the impl of `Reply` for `(Result<impl Reply, Rejection>,)`
note: required by a bound in `serve`
  --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.3.2/src/server.rs:26:17
   |
26 |     F::Extract: Reply,
   |                 ^^^^^ required by this bound in `serve`

error[E0277]: the trait bound `Result<impl Reply, Rejection>: Reply` is not satisfied
   --> src/main.rs:21:10
    |
21  |         .run(([127, 0, 0, 1], 3030))
    |          ^^^ the trait `Reply` is not implemented for `Result<impl Reply, Rejection>`
    |
    = help: the following implementations were found:
              <Result<T, http::Error> as Reply>
    = note: required because of the requirements on the impl of `Reply` for `(Result<impl Reply, Rejection>,)`
note: required by a bound in `warp::Server::<F>::run`
   --> ~/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.3.2/src/server.rs:127:35
    |
127 |     <F::Future as TryFuture>::Ok: Reply,
    |                                   ^^^^^ required by this bound in `warp::Server::<F>::run`

This appears to be the same kind of issue as described in Warp: the trait `warp::reply::Reply` is not implemented but I have not been able to work out from that what I'm getting wrong.

If I've understood error message and the warp docs right, Reply is implemented for Result<T, http::Error> but presumably warp::Rejection is not being implicitly interpreted as an http::Error, and hence there is no built-in Reply implementation for my actual Result return-type.

Can anyone help me understand what am I getting wrong here? I had understood from various tutorials that Result<impl warp::Reply, warp::Rejection> was a typical return type for functions designed to implement API requests.

Well why should it? Those are two completely different types.


I never used warp, but looking at one of the first Google hits, it seems like map() is designed to work with non-rejecting responses, and whenever you want to return a Result<T, Rejection>, you have to use and_then() instead – unsurprisingly, this is in line with the naming convention of std types.

1 Like

I am aware of that :wink: The problem is not understanding why the compiler is objecting, but understanding what the right thing to do is.

Ah! That was the piece I was missing, I must have missed it when reading through examples. Thanks for spotting it!

This code works (note that it was also necessary to make the get_hello function async):

use warp::Filter;

async fn get_hello(name: String) -> std::result::Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::with_status(
        format!("Hello {}\n", name),
        http::StatusCode::OK
    ))
}

#[tokio::main]
async fn main() {
    let routes = warp::get()
        .and(warp::path("hello"))
        .and(warp::path::param())
        .and_then(get_hello);

    warp::serve(routes)
        .run(([127, 0, 0, 1], 3030))
        .await;
}

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.