Skip to content

Commit f1ae6e9

Browse files
committed
Fix trim trailing slash middleware
The axum docs point out that any middleware that should affect routing must wrap the Router. In 0.6.12 we rely on a bug in axum routing that allows the trailing slash middleware to work on nested paths (but fails on root paths). In 0.6.13 onwards this bug is no longer present, so we lose the trailing slash removal. This change fixes the issue. tokio-rs/axum#1978 https://docs.rs/axum/0.6.18/axum/middleware/index.html#rewriting-request-uri-in-middleware
1 parent 6814764 commit f1ae6e9

File tree

4 files changed

+27
-7
lines changed

4 files changed

+27
-7
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ thiserror = "1.0"
3333
tokio = { version = "1.28", features = ["full"] }
3434
tower = "0.4"
3535
tower-http = { version = "0.4", features = ["normalize-path", "trace", "validate-request"] }
36+
tower-service = "0.3"
3637
tokio-stream = "0.1"
3738
tracing = "0.1"
3839
tracing-subscriber = { version = "0.3", features = ["env-filter"] }

src/app.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use axum::{
1919
Router, TypedHeader,
2020
};
2121

22+
use tower::Layer;
2223
use tower::ServiceBuilder;
2324
use tower_http::normalize_path::NormalizePathLayer;
2425
use tower_http::trace::TraceLayer;
@@ -54,9 +55,7 @@ impl IntoResponse for models::Response {
5455
/// * a [tower_http::trace::TraceLayer] for tracing requests and responses
5556
/// * a [tower_http::validate_request::ValidateRequestHeaderLayer] for validating authorisation
5657
/// headers
57-
/// * a [tower_http::normalize_path::NormalizePathLayer] for trimming trailing slashes from
58-
/// requests
59-
pub fn router() -> Router {
58+
fn router() -> Router {
6059
fn v1() -> Router {
6160
Router::new()
6261
.route("/count", post(operation_handler::<operations::Count>))
@@ -85,7 +84,25 @@ pub fn router() -> Router {
8584
Router::new()
8685
.route("/.well-known/s3-active-storage-schema", get(schema))
8786
.nest("/v1", v1())
88-
.layer(NormalizePathLayer::trim_trailing_slash())
87+
}
88+
89+
/// Returns a [tower_service::Service] for the Active Storage server API
90+
///
91+
/// The service is populated with all routes as well as the following middleware:
92+
///
93+
/// * a [tower_http::trace::TraceLayer] for tracing requests and responses
94+
/// * a [tower_http::validate_request::ValidateRequestHeaderLayer] for validating authorisation
95+
/// headers
96+
/// * a [tower_http::normalize_path::NormalizePathLayer] for trimming trailing slashes from
97+
/// requests
98+
pub fn service() -> tower_http::normalize_path::NormalizePath<Router> {
99+
// FIXME: The return type should be some form of tower_service::Service, but couldn't find the
100+
// necessary trait bounds.
101+
102+
// Note that any middleware that should affect routing must wrap the router.
103+
// See
104+
// https://docs.rs/axum/0.6.18/axum/middleware/index.html#rewriting-request-uri-in-middleware.
105+
NormalizePathLayer::trim_trailing_slash().layer(router())
89106
}
90107

91108
/// TODO: Return an OpenAPI schema

src/main.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
2525
use std::{net::SocketAddr, process::exit, str::FromStr, time::Duration};
2626

27+
use axum::ServiceExt;
2728
use axum_server::{tls_rustls::RustlsConfig, Handle};
2829
use clap::Parser;
2930
use expanduser::expanduser;
@@ -77,7 +78,7 @@ async fn main() {
7778

7879
init_tracing();
7980

80-
let router = app::router();
81+
let service = app::service();
8182
let addr = SocketAddr::from_str(&format!("{}:{}", args.host, args.port))
8283
.expect("invalid host name, IP address or port number");
8384

@@ -120,14 +121,14 @@ async fn main() {
120121
// run HTTPS server with hyper
121122
axum_server::bind_rustls(addr, tls_config)
122123
.handle(handle)
123-
.serve(router.into_make_service())
124+
.serve(service.into_make_service())
124125
.await
125126
.unwrap();
126127
} else {
127128
// run HTTP server with hyper
128129
axum_server::bind(addr)
129130
.handle(handle)
130-
.serve(router.into_make_service())
131+
.serve(service.into_make_service())
131132
.await
132133
.unwrap();
133134
}

0 commit comments

Comments
 (0)