Using Request<Body> multiple times

0

I am trying to read request body using (req.into_body()) and generate a hash key based on parameters (request.uri and request.body) but as documentation states req.into_body() will consume request so I can't use the same variable below that line.

Question:

So how can I reuse the request variable consuming it. There is no clone function for request body either that I can use to replicate variable.

Below is the given sample code.

async fn readKey(req: Request<Body>) -> (String, Request<Body>) {
    let mut key: String;
    if (!req.method().as_str().eq("GET")) {
        let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap();
        let body_string = String::from_utf8(body_bytes.to_vec()).unwrap();
        key = format!(
            "{}{}{}",
            req.uri().host().unwrap(),
            req.uri().path(),
            body_string
        );
    } else {
        key = format!("{}{}", req.uri().host().unwrap(), req.uri().path());
    }
    return (key, req);
}

Compilation Error

error[E0382]: borrow of moved value: `req`
   --> src/main.rs:72:33
    |
65  | async fn readKey(req: Request<Body>) -> (String , Request<Body>) {
    |                  --- move occurs because `req` has type `Request<Body>`, which does not implement the `Copy` trait
...
70  |         let body_bytes = hyper::body::to_bytes(req.into_body()).await.unwrap();
    |                                                    ----------- `req` moved due to this method call
71  |         let body_string = String::from_utf8(body_bytes.to_vec()).unwrap();
72  |         key = format!("{}{}{}", req.uri().host().unwrap(), req.uri().path(),body_string);
    |                                 ^^^^^^^^^ value borrowed here after move
    |
note: `Request::<T>::into_body` takes ownership of the receiver `self`, which moves `req`
   --> /Users/sunilsingh/.cargo/registry/src/github.com-1ecc6299db9ec823/http-0.2.9/src/request.rs:653:22
    |
653 |     pub fn into_body(self) -> T {
    |                      ^^^^

I used something like:

let body: Vec<u8> = body
    .collect()
    .await
    .to_bytes()
    .into(); 
1 Like
use hyper::{Request, Body};
async fn readKey(mut req: Request<Body>) -> (String, Request<Body>) {
    let key: String;
    if !req.method().as_str().eq("GET") {
        // destructure the request so we can get the body & other parts separately
        let (parts, body) = req.into_parts();
        let body = hyper::body::to_bytes(body).await.unwrap();
        let body = String::from_utf8(body.to_vec()).unwrap();
        key = format!(
            "{}{}{}",
            parts.uri.host().unwrap(),
            parts.uri.path(),
            body
        );
        // reconstruct the Request from parts and the data in `body`
        req = Request::from_parts(parts, body.into());
    } else {
        key = format!("{}{}", req.uri().host().unwrap(), req.uri().path());
    }

    return (key, req);
}

I suggest reordering the code instead — make the key first, and/or clone the uri, before transforming the request into body.

There's also into_parts()

2 Likes

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.