Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update middleware.md - existing documentation doesn't compile #3231

Closed
wants to merge 1 commit into from

Conversation

CrypticError
Copy link

I ran into an issue following the documentation trying to implement a uri-rewrite middleware.

Found https://users.rust-lang.org/t/rewrite-request-uri-in-middleware-for-axum/104619 - which fixed this issue, so updating the doc to reflect this

Motivation

Solution

I ran into an issue following the documentation trying to implement a uri-rewrite middleware.

Found https://users.rust-lang.org/t/rewrite-request-uri-in-middleware-for-axum/104619 - which fixed this issue, so updating the doc to reflect this
@mladedav
Copy link
Collaborator

When I copy the original code from docs it compiles for me. CI also fails on the changes you made because that documentation example does not seem to compile.

The issue you linked also seems to have been caused by an incorrect signature of the middleware.

Can you try providing a full example of what regarding this example does not compile for you?

@CrypticError
Copy link
Author

Hmm, this code errors for me with some very unhelpful error messages.

pub async fn api_versioning_middleware<B>(mut req: Request<B>) -> Request<B> {
    let path = req.uri().path();

    let version = API_VERSIONING_PATTERN
        .captures(path)
        .and_then(|x| x.get(1).map(|m| ApiVersion::from_str(m.as_str())))
        .unwrap_or_else(|| Ok(ApiVersion::latest()))
        .unwrap_or(ApiVersion::latest());

    let new_path = API_VERSIONING_PATTERN.replace(path, "/").to_string();
    let new_uri = Builder::new().path_and_query(new_path).build().unwrap();
    *req.uri_mut() = new_uri;

    req.extensions_mut().insert(version);
    req
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // this can be any `tower::Layer`
    let middleware = tower::util::MapRequestLayer::new(api_versioning_middleware);

    let app = Router::new();

    // apply the layer around the whole `Router`
    // this way the middleware will run before `Router` receives the request
    let app_with_middleware = middleware.layer(app);

    let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
    axum::serve(listener, app_with_middleware.into_make_service())
        .await
        .unwrap();
    Ok(())
}
error[E0599]: the method `into_make_service` exists for struct `MapRequest<Router<_>, ...>`, but its trait bounds were not satisfied
  --> app\api-backend\src\main.rs:83:47
   |
83 |     axum::serve(listener, app_with_middleware.into_make_service())
   |                                               ^^^^^^^^^^^^^^^^^ method cannot be called on `MapRequest<Router<_>, ...>` due to unsatisfied trait bounds
   |
  ::: C:\Users\user\.cargo\registry\src\index.crates.io-6f17d22bba15001f\tower-0.5.2\src\util\map_request.rs:10:1
   |
10 | pub struct MapRequest<S, F> {
   | --------------------------- doesn't satisfy `_: Service<_>` or `_: ServiceExt<_>`
   |
   = note: the full type name has been written to 'C:\Users\user\RustroverProjects\apex-monorepo\target\debug\deps\api_backend.long-type-10123062717469459164.txt'
   = note: consider using `--verbose` to print the full type name to the console
   = note: the following trait bounds were not satisfied:
           `tower::util::MapRequest<Router<_>, fn(axum::http::Request<_>) -> impl Future<Output = axum::http::Request<_>> {api_versioning_middleware::<_>}>: Service<_>`
           which is required by `tower::util::MapRequest<Router<_>, fn(axum::http::Request<_>) -> impl Future<Output = axum::http::Request<_>> {api_versioning_middleware::<_>}>: axum::ServiceExt<_>`
           `&tower::util::MapRequest<Router<_>, fn(axum::http::Request<_>) -> impl Future<Output = axum::http::Request<_>> {api_versioning_middleware::<_>}>: Service<_>`
           which is required by `&tower::util::MapRequest<Router<_>, fn(axum::http::Request<_>) -> impl Future<Output = axum::http::Request<_>> {api_versioning_middleware::<_>}>: axum::ServiceExt<_>`
           `&mut tower::util::MapRequest<Router<_>, fn(axum::http::Request<_>) -> impl Future<Output = axum::http::Request<_>> {api_versioning_middleware::<_>}>: Service<_>`
           which is required by `&mut tower::util::MapRequest<Router<_>, fn(axum::http::Request<_>) -> impl Future<Output = axum::http::Request<_>> {api_versioning_middleware::<_>}>: axum::ServiceExt<_>`

Cargo.toml dependencies

[dependencies]
anyhow = "1.0"
indexmap = { version = "2.7", features = ["serde"] }
serde = { version = "1.0", features = ["derive"] }
sqlx = { version = "0.8", features = ["postgres", "runtime-tokio", "tls-rustls"] }
toml = "0.8"
tokio = { version = "1.43", features = ["full"] }
axum = "0.8"
tower = { version = "0.5", features = ["util"] }
serde_json = "1.0"
regex = "1.11"
rand = "0.9"
base64 = "0.22"
argon2 = "0.5"
axum-macros = "0.5.0"
zxcvbn = "3.1.0"
validator = { version = "0.20.0", features = ["derive"] }
lazy_static = "1.5.0"

Sorry I am very new to rust, so it could be some horrible oversight on my part, but assume it was just outdated documentation due to the linked changes working.

@CrypticError
Copy link
Author

I just noticed that my signature differs from the one in the doc, as I am taking a mutable reference.

It seems like axom::middleware::map_request is already documented on this change difference.

Create a middleware from an async function that transforms a request.
This differs from tower::util::MapRequest in that it allows you to easily run axum-specific extractors

I guess the thing that I actually want is better error messages, but that is clearly out of scope.

Thanks for your time looking into this, and sorry for the inconvenience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants