@@ -25,6 +25,56 @@ pub use axum_macros::TypedPath;
25
25
#[ cfg( feature = "typed-routing" ) ]
26
26
pub use self :: typed:: { SecondElementIs , TypedPath } ;
27
27
28
+ // Validates a path at compile time, used with the vpath macro.
29
+ #[ rustversion:: since( 1.80 ) ]
30
+ #[ doc( hidden) ]
31
+ pub const fn __private_validate_static_path ( path : & ' static str ) -> & ' static str {
32
+ if path. is_empty ( ) {
33
+ panic ! ( "Paths must start with a `/`. Use \" /\" for root routes" )
34
+ }
35
+ if path. as_bytes ( ) [ 0 ] != b'/' {
36
+ panic ! ( "Paths must start with /" ) ;
37
+ }
38
+ path
39
+ }
40
+
41
+ /// This macro aborts compilation if the path is invalid.
42
+ ///
43
+ /// This example will fail to compile:
44
+ ///
45
+ /// ```compile_fail
46
+ /// use axum::routing::{Router, get};
47
+ /// use axum_extra::vpath;
48
+ ///
49
+ /// let router = axum::Router::<()>::new()
50
+ /// .route(vpath!("invalid_path"), get(root))
51
+ /// .to_owned();
52
+ ///
53
+ /// async fn root() {}
54
+ /// ```
55
+ ///
56
+ /// This one will compile without problems:
57
+ ///
58
+ /// ```no_run
59
+ /// use axum::routing::{Router, get};
60
+ /// use axum_extra::vpath;
61
+ ///
62
+ /// let router = axum::Router::<()>::new()
63
+ /// .route(vpath!("/valid_path"), get(root))
64
+ /// .to_owned();
65
+ ///
66
+ /// async fn root() {}
67
+ /// ```
68
+ ///
69
+ /// This macro is available only on rust versions 1.80 and above.
70
+ #[ rustversion:: since( 1.80 ) ]
71
+ #[ macro_export]
72
+ macro_rules! vpath {
73
+ ( $e: expr) => {
74
+ const { $crate:: routing:: __private_validate_static_path( $e) }
75
+ } ;
76
+ }
77
+
28
78
/// Extension trait that adds additional methods to [`Router`].
29
79
pub trait RouterExt < S > : sealed:: Sealed {
30
80
/// Add a typed `GET` route to the router.
0 commit comments