From 18ee97d445d3783a921657088ef8b08360101eca Mon Sep 17 00:00:00 2001 From: Chrislearn Young Date: Mon, 29 Jul 2024 13:06:57 +0800 Subject: [PATCH] Save and use router param without wildcard --- crates/core/src/routing/filters/path.rs | 30 +++++++++++++++---------- crates/core/src/routing/mod.rs | 2 +- crates/oapi/src/swagger_ui/mod.rs | 2 +- examples/static-embed-file/src/main.rs | 4 ++-- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/crates/core/src/routing/filters/path.rs b/crates/core/src/routing/filters/path.rs index e4f4aa1e4..4a09bdbaf 100644 --- a/crates/core/src/routing/filters/path.rs +++ b/crates/core/src/routing/filters/path.rs @@ -254,13 +254,13 @@ impl PathWisp for CharsWisp { } if chars.len() == max_width { state.forward(max_width); - state.params.insert(self.name.clone(), chars.into_iter().collect()); + insert_param_to_state(state, &self.name, chars.into_iter().collect()); return true; } } if chars.len() >= self.min_width { state.forward(chars.len()); - state.params.insert(self.name.clone(), chars.into_iter().collect()); + insert_param_to_state(state, &self.name, chars.into_iter().collect()); true } else { false @@ -274,7 +274,7 @@ impl PathWisp for CharsWisp { } if chars.len() >= self.min_width { state.forward(chars.len()); - state.params.insert(self.name.clone(), chars.into_iter().collect()); + insert_param_to_state(state, &self.name, chars.into_iter().collect()); true } else { false @@ -403,7 +403,7 @@ impl PathWisp for NamedWisp { } if !rest.is_empty() || !self.0.starts_with("*+") { let rest = rest.to_string(); - state.params.insert(self.0.clone(), rest); + insert_param_to_state(state, &self.0, rest); state.cursor.0 = state.parts.len(); true } else { @@ -416,7 +416,7 @@ impl PathWisp for NamedWisp { } let picked = picked.expect("picked should not be `None`").to_owned(); state.forward(picked.len()); - state.params.insert(self.0.clone(), picked); + insert_param_to_state(state, &self.0, picked); true } } @@ -456,7 +456,7 @@ impl PathWisp for RegexWisp { if let Some(cap) = cap { let cap = cap.as_str().to_owned(); state.forward(cap.len()); - state.params.insert(self.name.clone(), cap); + insert_param_to_state(state, &self.name, cap); true } else { false @@ -472,7 +472,7 @@ impl PathWisp for RegexWisp { if let Some(cap) = cap { let cap = cap.as_str().to_owned(); state.forward(cap.len()); - state.params.insert(self.name.clone(), cap); + insert_param_to_state(state, &self.name, cap); true } else { false @@ -915,6 +915,17 @@ impl PathFilter { } } +#[inline] +fn insert_param_to_state(state: &mut PathState, name: &str, value: String) { + if name.starts_with("*+") || name.starts_with("*?") || name.starts_with("**") { + state.params.insert(name[2..].to_owned(), value); + } else if name.starts_with('*') { + state.params.insert(name[1..].to_owned(), value); + } else { + state.params.insert(name.to_owned(), value); + } +} + #[cfg(test)] mod tests { use super::PathParser; @@ -930,11 +941,6 @@ mod tests { let segments = PathParser::new("/").parse().unwrap(); assert!(segments.is_empty()); } - #[test] - fn test_parse_rest_without_name() { - let segments = PathParser::new("/hello/<**>").parse().unwrap(); - assert_eq!(format!("{:?}", segments), r#"[ConstWisp("hello"), NamedWisp("**")]"#); - } #[test] fn test_parse_single_const() { diff --git a/crates/core/src/routing/mod.rs b/crates/core/src/routing/mod.rs index e5f146102..6f5c28b3c 100644 --- a/crates/core/src/routing/mod.rs +++ b/crates/core/src/routing/mod.rs @@ -301,7 +301,7 @@ //! //! #[handler] //! fn serve_file(req: &mut Request) { -//! let rest_path = req.param::("**rest_path"); +//! let rest_path = req.param::("rest_path"); //! } //! ``` //! diff --git a/crates/oapi/src/swagger_ui/mod.rs b/crates/oapi/src/swagger_ui/mod.rs index d21950574..dc13d932a 100644 --- a/crates/oapi/src/swagger_ui/mod.rs +++ b/crates/oapi/src/swagger_ui/mod.rs @@ -233,7 +233,7 @@ pub(crate) fn redirect_to_dir_url(req_uri: &Uri, res: &mut Response) { #[async_trait] impl Handler for SwaggerUi { async fn handle(&self, req: &mut Request, _depot: &mut Depot, res: &mut Response, _ctrl: &mut FlowCtrl) { - let path = req.params().get("**").map(|s| &**s).unwrap_or_default(); + let path = req.params().last().map(|(_, s)| &**s).unwrap_or_default(); // Redirect to dir url if path is empty and not end with '/' if path.is_empty() && !req.uri().path().ends_with('/') { redirect_to_dir_url(req.uri(), res); diff --git a/examples/static-embed-file/src/main.rs b/examples/static-embed-file/src/main.rs index 5ecdbf0c5..6c58bc91a 100644 --- a/examples/static-embed-file/src/main.rs +++ b/examples/static-embed-file/src/main.rs @@ -10,7 +10,7 @@ struct Assets; async fn main() { tracing_subscriber::fmt().init(); - let router = Router::with_path("<*path>").get(serve_file); + let router = Router::with_path("<**rest>").get(serve_file); let acceptor = TcpListener::new("0.0.0.0:5800").bind().await; Server::new(acceptor).serve(router).await; @@ -18,7 +18,7 @@ async fn main() { #[handler] async fn serve_file(req: &mut Request, res: &mut Response) { - let path = req.param::("*path").unwrap(); + let path = req.param::("rest").unwrap(); if let Some(file) = Assets::get(&path) { file.render(req, res); } else {