Improve typed path by disallowing deprecated variable definitions (#3618)

This commit is contained in:
Tomaz Canabrava
2026-03-19 12:42:00 +01:00
committed by GitHub
parent da26db264f
commit 20dfe6645d
2 changed files with 41 additions and 1 deletions
+3
View File
@@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning].
- **fixed:** Escape backslashes and double quotes in `Content-Disposition` filenames - **fixed:** Escape backslashes and double quotes in `Content-Disposition` filenames
to prevent header parameter injection in `Attachment` and `FileStream` ([#3664]) to prevent header parameter injection in `Attachment` and `FileStream` ([#3664])
- `vpath!` macro now stops the compilation if your path is using deprecated
path variables in the old `107` format, such as `:var` and `*var`. the
only allowed way now is `{var}`.
- **breaking:** Remove the deprecated `Host`, `Scheme` and `OptionalPath` - **breaking:** Remove the deprecated `Host`, `Scheme` and `OptionalPath`
extractors ([#3599]) extractors ([#3599])
- Also remove `HostRejection` which only had `FailedToResolveHost` - Also remove `HostRejection` which only had `FailedToResolveHost`
+38 -1
View File
@@ -36,6 +36,20 @@ pub const fn __private_validate_static_path(path: &'static str) -> &'static str
if path.as_bytes()[0] != b'/' { if path.as_bytes()[0] != b'/' {
panic!("Paths must start with /"); panic!("Paths must start with /");
} }
// Checks if we have a path in 107 format.
let size: usize = path.len() - 1;
let mut curr: usize = 0;
let bytes = path.as_bytes();
while curr < size {
if bytes[curr] == b'/' && (bytes[curr + 1] == b'*' || bytes[curr + 1] == b':') {
panic!(
"You have a path with a deprecated format, move your ':var' or '*var' to '{{var}}'"
);
}
curr += 1;
}
path path
} }
@@ -61,12 +75,35 @@ pub const fn __private_validate_static_path(path: &'static str) -> &'static str
/// use axum_extra::vpath; /// use axum_extra::vpath;
/// ///
/// let router = axum::Router::<()>::new() /// let router = axum::Router::<()>::new()
/// .route(vpath!("/valid_path"), get(root)) /// .route(vpath!("/valid_path/{id}"), get(root))
/// .to_owned(); /// .to_owned();
/// ///
/// async fn root() {} /// async fn root() {}
/// ``` /// ```
/// ///
/// It also checks for deprecated usage of variables within the path:
///
/// ```compile_fail
/// use axum::routing::{Router, get};
/// use axum_extra::vpath;
///
/// let router = axum::Router::<()>::new()
/// .route(vpath!("/users/:id"), get(root))
/// .to_owned();
///
/// async fn root() {}
/// ```
///
/// ```compile_fail
/// use axum::routing::{Router, get};
/// use axum_extra::vpath;
///
/// let router = axum::Router::<()>::new()
/// .route(vpath!("/users/*id"), get(root))
/// .to_owned();
///
/// async fn root() {}
/// ```
/// This macro is available only on rust versions 1.80 and above. /// This macro is available only on rust versions 1.80 and above.
#[cfg_attr(docsrs, doc(cfg(feature = "routing")))] #[cfg_attr(docsrs, doc(cfg(feature = "routing")))]
#[rustversion::since(1.80)] #[rustversion::since(1.80)]