user6475988
user6475988

Reputation: 87

How to obtain full body in Axum handler?

I want to use the Axum framework of Rust in the following way: Suppose there is a request incoming with a request body. I want to obtain the request body, inspect it, possibly change parts of it and use that to create a response.

However, I'm stuck at obtaining the request body in a appropriate way to be able to handle it. I guess it should be enough if I know how to convert to something like a vector of bytes or being able to print its content. Please note it is ok to assume that the body would consist of something which can be converted to a UTF-8 string or JSON.

use axum::body::Body;
use axum::http::Request;
use axum::response::IntoResponse;
use axum::Json;
use hyper::StatusCode;
use serde_json::json;

pub async fn modder(mut request: Request<Body>) -> impl IntoResponse {
    let body = request;
    // What to I need to do here, to obtain the body in an appropiate way (e.g. bytes)?

    let response = json!({
        "data": {
              "values": "transformed body",
         },
    });
    (StatusCode::OK, Json(response))
}

How do I need to change the code? I would appreciate answer which are also in line with the newest version of axum.

Upvotes: 2

Views: 5102

Answers (3)

adic threex
adic threex

Reputation: 109

Also you can get body from request:

pub async fn handler(request: axum::http::Request<axum::body::Body>) -> impl IntoResponse  {
    let limit = 2048usize;
    let body = request.into_body();
    let bytes = axum::body::to_bytes(body, limit).await.unwrap();
    let body_str = String::from_utf8(bytes.to_vec()).unwrap();
    println!("Body: {}", body_str);
}

It may be useful when you need to process headers and then decide how to process body or any other case where you need a lower level.

Upvotes: 2

kmdreko
kmdreko

Reputation: 60497

Axum uses extractors to get typed-data from the request or the framework itself. These are expressed as distinct parameters on a handler function. Extractors that can access the request body implement FromRequest (since the FromRequestParts variation can only see things from the request header: i.e. method, path, headers, etc).

From there, your main options are:

  • String if you want to buffer the whole body and are expecting UTF-8 encoded text
  • Bytes (similar to Vec<u8>) if you want to buffer the whole body and are expecting binary or other non-UTF-8 data
  • Json, Form, Multipart, etc. if you want to deserialize the body from a structured format into a typed structure
  • Body if you don't need the whole body to be buffered and want to handle a stream of bytes instead.

So yours could look simply like this:

pub async fn modder(body: String) -> impl IntoResponse {
    // do stuff with body

    ...
}

NOTE: Since only one extractor can extract the body, it must be the last parameter. More info

Upvotes: 2

Bion Alex Howard
Bion Alex Howard

Reputation: 104

Looks like this link

https://docs.rs/axum/latest/axum/extract/index.html

Has examples of what you might be looking for. Especially the part here

https://docs.rs/axum/latest/axum/extract/index.html#the-order-of-extractors

Might need to implement this trait FromRequest for your desired data structure.

https://docs.rs/axum/latest/axum/extract/trait.FromRequest.html

Which involves this Request from a different crate, http:

https://docs.rs/http/1.1.0/http/request/struct.Request.html

Then Axum library uses that to wrap their Body type here https://docs.rs/axum/latest/axum/body/struct.Body.html

Probably many ways to do this, the idiomatic Rust way would be to implement From, the idiomatic Axum approach might be to implement FromRequest for your data structure.

you might need to define input and output data structures to handle FromRequest and IntoResponse respectively.

Might need a different modder (I suggest verb names for functions btw, use nouns like modder for data) for each kind of modification (presumably, route)

Upvotes: 0

Related Questions