1

I am trying to log request / response bodies in warp.

When using warp::log::custom, the Info struct doesn't contain any info about it.

When trying to implement my own log wrapper, based on the implementation of warp::log, the Route struct is private (among others).

I can log bodies after they are deserialized using

warp::body::json().map(|it| {
    println!("Hello : {:?}", it);
    it
})

But if the user doesn't send a correct body, it wont work. Moreover, I am looking for a simple way to log all requests bodies.

Ltei
  • 425
  • 1
  • 6
  • 14

1 Answers1

8

I have stumbled upon this while searching for the solution myself so maybe it will be useful for someone in the future.

You can use warp::body::bytes() to get body not necessarily in json format:

warp::body::bytes()
    .map(|b: Bytes| {
        println!("Request body: {}", std::str::from_utf8(b.bytes()).expect("error converting bytes to &str"));

        "Hello, World!"
    }

To make it more universal I have managed to make a function which I can use in my filters easily:

fn log_body() -> impl Filter<Extract = (), Error = Rejection> + Copy {
    warp::body::bytes()
        .map(|b: Bytes| {
            println!("Request body: {}", std::str::from_utf8(b.bytes()).expect("error converting bytes to &str"));
        })
        .untuple_one()
}

It can be then used as such:

    let api = warp::any()
        .and(log_body())
        .and_then(handle);

For a full example, you can check out the gist I have prepared.

Szymig
  • 555
  • 5
  • 9
  • 1
    @nbari That will be something like this https://gist.github.com/Szymongib/c051c56e8eba8f6464a448e809c370c0 – Szymig Sep 19 '20 at 07:31
  • 2023, b.bytes() seems to work no more. To fix this you need to run map on bytes like this: .map(|b: Bytes| { let v = b.to_vec(); let c = &*v; println!("Request body: {}", std::str::from_utf8(c).expect("error converting bytes to &str")); }) .untuple_one() – Chris Jul 18 '23 at 15:23