tokio-rs/axum

`middleware::from_fn` fails if fn calls async fn with `&Request` argument

Closed this issue · 0 comments

  • I have looked for existing issues (including closed) about this

Bug Report

Version

axum v0.7.4
axum-core v0.4.3

Platform

Linux work 6.7.2-1-default #1 SMP PREEMPT_DYNAMIC Fri Jan 26 11:01:28 UTC 2024 (a52bf76) x86_64 x86_64 x86_64 GNU/Linux

Description

middleware::from_fn fails if the provided function calls another async function that takes &Request as argument.

I tried this code:

use axum::{
    extract::Request,
    http::StatusCode,
    middleware::{self, Next},
    response::Response,
    Router,
};

async fn auth(request: Request, next: Next) -> Result<Response, StatusCode> {
    get_token(&request).await;

    todo!()
}

async fn get_token(request: &Request) {
    todo!()
}

fn main() {
    Router::<()>::new().route_layer(middleware::from_fn(auth));
}

I got this compiler error:

error[E0277]: the trait bound `axum::middleware::FromFn<fn(axum::http::Request<axum::body::Body>, axum::middleware::Next) -> impl std::future::Future<Output = std::result::Result<axum::http::Response<axum::body::Body>, axum::http::StatusCode>> {auth}, (), axum::routing::Route, _>: tower_service::Service<axum::http::Request<axum::body::Body>>` is not satisfied
   --> src/main.rs:20:37
    |
20  |     Router::<()>::new().route_layer(middleware::from_fn(auth));
    |                         ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `tower_service::Service<axum::http::Request<axum::body::Body>>` is not implemented for `FromFn<fn(Request<Body>, Next) -> impl Future<Output = Result<Response<Body>, ...>> {auth}, ..., ..., ...>`
    |                         |
    |                         required by a bound introduced by this call
    |
    = help: the following other types implement trait `tower_service::Service<Request>`:
              axum::middleware::FromFn<F, S, I, (T1,)>
              axum::middleware::FromFn<F, S, I, (T1, T2)>
              axum::middleware::FromFn<F, S, I, (T1, T2, T3)>
              axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4)>
              axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5)>
              axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6)>
              axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7)>
              axum::middleware::FromFn<F, S, I, (T1, T2, T3, T4, T5, T6, T7, T8)>
            and 8 others
note: required by a bound in `axum::Router::<S>::route_layer`
   --> /home/daniel/.cargo/registry/src/index.crates.io-6f17d22bba15001f/axum-0.7.4/src/routing/mod.rs:296:21
    |
293 |     pub fn route_layer<L>(self, layer: L) -> Self
    |            ----------- required by a bound in this associated function
...
296 |         L::Service: Service<Request> + Clone + Send + 'static,
    |                     ^^^^^^^^^^^^^^^^ required by this bound in `Router::<S>::route_layer`

The error can be avoided by either changing the get_token function to be sync, or by not passing a reference to the request.