0

I'm trying to implement a fairing in Rocket that logs the bodies of requests coming in. Unfortunately, since the fairing on_request method only gets a reference to the rocket::Data in the request, I can't call data.open().

Here's the fairing I have so far:

#[derive(Default)]
struct Logger {
}

impl Fairing for Logger {
    fn info(&self) -> Info {
        Info {
            name: "Request / response logger",
            kind: Kind::Request | Kind::Response
        }
    }

    fn on_request(&self, request: &mut Request, data: &Data) {
        if request.method() == Method::Post {
            println!("Request came in!");
            let mut dataStr = "".to_string();
            data.open().read_to_string(&mut dataStr);
            println!("{:?}", dataStr);
        }
    }

    fn on_response(&self, request: &Request, response: &mut Response) {
    }
}

Unsurprisingly, I get this error:

379 |        data.open().read_to_string(&mut dataStr);
    |        ^^^^ cannot move out of borrowed content

Is there any way to log the data without consuming it? If not, is there another way to implement a logging fairing like this?

Marcus Buffett
  • 1,289
  • 1
  • 14
  • 32
  • [`fn open(self)`](https://api.rocket.rs/rocket/struct.Data.html#method.open) *The method consumes the `Data` instance.* You could maybe use `peek` instead. – Henri Menke Jan 14 '18 at 01:36

1 Answers1

0

Is there any way to log the data without consuming it?

No. Check out the documentation for Data::open:

Returns the raw data stream.

The stream contains all of the data in the body of the request, including that in the peek buffer. The method consumes the Data instance. This ensures that a Data type always represents all of the data in a request.

HTTP request bodies are streams of data. These streams are read-once. If you were to log the body of the request, the data would then be gone and your actual handler would have nothing to work with.

is there another way to implement a logging fairing like this?

I don't know of any, but it seems like a brittle idea to start with. If someone were to POST a 1GB file, do you really want that entire thing logged?

The closest alternative I can think of is to take the owned Data in the handler, open it up, then "tee" the output of it to both your real code and save it somewhere, log-wise.

See also:

Community
  • 1
  • 1
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366