How to get Request details & as well as json body from axum?

Can anyone please help me to understand, how can I get request details & Json body from handler?

Thanks

E.g.

async fn set_value(
    State(app_state): State<Arc<Mutex<AppState>>>,
    Json(b): Json<AppState>,
    req: Request<Body>,
) -> impl IntoResponse {
    // This is an example, there will be multiple condition based on request method or user-agent
    if req.method() == Method::GET {
        println!("Get Request");
    } else {
        println!("Post Request");
    }

    let mut app_state: MutexGuard<AppState> = app_state
        .lock()
        .map_err(|_| error!("Fail to lock mutex"))
        .unwrap();

    *app_state = b;

    let r: String = serde_json::to_string(&b)
        .map_err(|_| error!("Fail to serialize"))
        .unwrap();

    Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "application/json")
        .body(r)
        .map_err(|_| error!("Fail to build response"))
        .unwrap()
}

Error

rror[E0277]: the trait bound `fn(axum::extract::State<Arc<std::sync::Mutex<AppState>>>, Json<AppState>, Request<Body>) -> impl Future<Output = impl IntoResponse> {set_value}: Handler<_, _, _>` is not satisfied
   --> src/main.rs:187:50
    |
187 |     let router = router.route("/set-value", post(set_value));
    |                                             ---- ^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(axum::extract::State<Arc<std::sync::Mutex<AppState>>>, Json<AppState>, Request<Body>) -> impl Future<Output = impl IntoResponse> {set_value}`
    |                                             |
    |                                             required by a bound introduced by this call

What's wrong with this example? I don't get what you are trying to do and what happens instead.

Issue is I am getting this error

rror[E0277]: the trait bound `fn(axum::extract::State<Arc<std::sync::Mutex<AppState>>>, Json<AppState>, Request<Body>) -> impl Future<Output = impl IntoResponse> {set_value}: Handler<_, _, _>` is not satisfied
   --> src/main.rs:187:50
    |
187 |     let router = router.route("/set-value", post(set_value));
    |                                             ---- ^^^^^^^^^ the trait `Handler<_, _, _>` is not implemented for fn item `fn(axum::extract::State<Arc<std::sync::Mutex<AppState>>>, Json<AppState>, Request<Body>) -> impl Future<Output = impl IntoResponse> {set_value}`
    |                                             |
    |                                             required by a bound introduced by this call

I think you're hitting the recent changes to Axum that promote a run time error to a compile time error

See "Type safe extractor ordering" in this blog post

If you want to extract the whole request you can't use other extractors after that, and any body extractor conflicts with another body extractor (extracting the whole request also extracts the body)

When you hit a trait bound error, you should check the implementations. In this case, the 3-argument function applies:

impl<F, Fut, S, B, Res, M, T1, T2, T3> Handler<(M, T1, T2, T3), S, B> for F
where
    F: FnOnce(T1, T2, T3) -> Fut + Clone + Send + 'static,
    Fut: Future<Output = Res> + Send,
    B: Send + 'static,
    S: Send + Sync + 'static,
    Res: IntoResponse,
    T1: FromRequestParts<S> + Send,
    T2: FromRequestParts<S> + Send,
    T3: FromRequest<S, B, M> + Send,

From there, you can check which types implement the traits FromRequestParts and FromRequest.

Thanks
But now, how I am suppose to get both?
Even extensions are not accessible if I extract Request.
:smiling_face_with_tear:

You can access the extensions directly on the Request. Generally it's simpler to just create your own extractor though since that's more compatible with other extractors (assuming you implement FromRequestParts and not FromRequest)

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.