rustrust-tokiorust-warp

Warp: single route works, multiple with .or() do not


Hoping someone can help me understand why running warp with a single route like this compiles fine:

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // GET /stats
    let stats = warp::get()
        .and(warp::path("stats"))
        .map(|| {
            let mut sys = System::new_all();
            sys.refresh_all();

            let local = LocalSystem::from_sys(&sys);
            warp::reply::json(&local);
        });

    // GET /
    let index = warp::get()
        .and(warp::path::end())
        .map(|| warp::reply::json(&last_ten_logs()));

    warp::serve(index).run(([127, 0, 0, 1], 4000)).await;

    Ok(())
}

But changing the warp::serve() line to serve two routes like in the examples in the repo causes a compilation error:

error[E0277]: the trait bound `(): Reply` is not satisfied
   --> src/main.rs:140:17
    |
140 |     warp::serve(stats.or(index)).run(([127, 0, 0, 1], 4000)).await;
    |     ----------- ^^^^^^^^^^^^^^^ the trait `Reply` is not implemented for `()`
    |     |
    |     required by a bound introduced by this call
    |
    = note: required because of the requirements on the impl of `Reply` for `((),)`
    = note: 2 redundant requirements hidden
    = note: required because of the requirements on the impl of `Reply` for `(warp::generic::Either<((),), (Json,)>,)`

I don't understand what the compiler is asking me to change.


Solution

  • The error is explicit:

    the trait Reply is not implemented for ()

    The problem is that your stats endpoint do not return anything, just remove the last ; so it gets returned as the last expresion in the closure:

    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        // GET /stats
        let stats = warp::get()
            .and(warp::path("stats"))
            .map(|| {
                let mut sys = System::new_all();
                sys.refresh_all();
    
                let local = LocalSystem::from_sys(&sys);
                warp::reply::json(&local)
            });
        ...
    }