How to write a simple warp handler returning json or html?

2.5k views Asked by At

I have the following:

use warp::Filter;

pub struct Router {}

impl Router {
    pub async fn handle(
        &self,
    ) -> std::result::Result<impl warp::Reply, warp::Rejection> {

        let uri = "/path";

        match uri {
            "/metrics-list" => {
                let empty : Vec<u8> = Vec::new();
                Ok(warp::reply::json(&empty))
            }

            "/metrics-ips" => {
                let empty : Vec<u8> = Vec::new();
                Ok(warp::reply::json(&empty))
            }

            &_ => {
                Err(warp::reject::reject())
            }
        }
    }
}

#[tokio::main]
pub async fn main() {
    let r = Router {};

    let handler = warp::path("/").map(|| r.handle());

    warp::serve(handler);
    // .run(([0, 0, 0, 0], 3000))
    // .await;
}

But even with this simplified example I get an error:

error[E0277]: the trait bound `impl warp::Future: warp::Reply` is not satisfied
  --> src/main.rs:41:17
   |
41 |     warp::serve(handler);
   |                 ^^^^^^^ the trait `warp::Reply` is not implemented for `impl warp::Future`
   |
  ::: $HOME/.cargo/registry/src/github.com-1ecc6299db9ec823/warp-0.2.5/src/server.rs:26:17
   |
26 |     F::Extract: Reply,
   |                 ----- required by this bound in `warp::serve`
   |
   = note: required because of the requirements on the impl of `warp::Reply` for `(impl warp::Future,)`

Why is that?

1

There are 1 answers

0
mirosval On

One solution is to call .into_response() on all your replies and then change the return type from std::result::Result<impl warp::Reply, warp::Rejection> to std::result::Result<warp::reply::Response, warp::Rejection>

pub async fn handle(
        &self,
    ) -> std::result::Result<warp::reply::Response, warp::Rejection> {

        let uri = "/path";

        match uri {
            "/metrics-list" => {
                let empty : Vec<u8> = Vec::new();
                Ok(warp::reply::json(&empty).into_response())
            }

            "/metrics-ips" => {
                let empty : Vec<u8> = Vec::new();
                Ok(warp::reply::json(&empty).into_response())
            }

            &_ => {
                Err(warp::reject::reject().into_response())
            }
        }
    }

The reason being if I understand this correctly that having an impl Trait in your return type lets you only use one type that implements that trait at once, since your function can ever only have one return type.