From 026b88d51b7d444700d1a5c997ee230e7ed63b15 Mon Sep 17 00:00:00 2001 From: midefos Date: Thu, 30 Jan 2025 01:27:21 +0100 Subject: [PATCH] adding url_extract to servme --- src/lib.rs | 2 ++ src/url_extract.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++ tests/url_extract.rs | 47 ++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 src/url_extract.rs create mode 100644 tests/url_extract.rs diff --git a/src/lib.rs b/src/lib.rs index 133fb5d..2ead33d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,7 +3,9 @@ mod config; mod requester; mod responder; mod server; +mod url_extract; pub use requester::Requester; pub use responder::Responder; pub use server::Server; +pub use url_extract::UrlExtract; diff --git a/src/url_extract.rs b/src/url_extract.rs new file mode 100644 index 0000000..0d80996 --- /dev/null +++ b/src/url_extract.rs @@ -0,0 +1,61 @@ +use http::Uri; +use std::collections::HashMap; + +pub struct UrlExtract { + params: HashMap, +} + +impl UrlExtract { + pub fn new(uri: &Uri) -> Self { + Self { + params: extract_params(uri), + } + } + + pub fn param_str(&self, param: &str) -> Option { + self.params.get(param).map(|param| Self::parse_param(param)) + } + + pub fn param_i64(&self, param: &str) -> Option { + self.params.get(param)?.parse().ok() + } + + pub fn param_f64(&self, param: &str) -> Option { + self.params.get(param)?.parse().ok() + } + + pub fn url_i64(uri: &Uri, match_path: &str) -> Option { + Self::extract_url(uri, match_path).first()?.parse().ok() + } + + pub fn url_str(uri: &Uri, match_path: &str) -> Option { + Self::extract_url(uri, match_path).first()?.parse().ok() + } + + fn extract_url(uri: &Uri, r#match: &str) -> Vec { + uri.path() + .trim_start_matches(r#match) + .split('/') + .map(|s| s.to_string()) + .collect() + } + + fn parse_param(param: &str) -> String { + param.replace("%20", " ") + } +} + +pub fn extract_params(uri: &Uri) -> HashMap { + uri.query() + .map(|q| { + q.split('&') + .map(|pair| { + let mut split = pair.splitn(2, '='); + let key = split.next().unwrap_or_default().to_string(); + let value = split.next().unwrap_or_default().to_string(); + (key, value) + }) + .collect() + }) + .unwrap_or_default() +} diff --git a/tests/url_extract.rs b/tests/url_extract.rs new file mode 100644 index 0000000..b3c324a --- /dev/null +++ b/tests/url_extract.rs @@ -0,0 +1,47 @@ +use servme::UrlExtract; + +#[test] +fn param_str() { + let uri = "https://example.com/path?param1=value1¶m2=value2¶m3=value%203" + .parse() + .unwrap(); + let extractor = UrlExtract::new(&uri); + + assert_eq!(extractor.param_str("param1"), Some("value1".to_string())); + assert_eq!(extractor.param_str("param2"), Some("value2".to_string())); + assert_eq!(extractor.param_str("param3"), Some("value 3".to_string())); + assert_eq!(extractor.param_str("nonexistent"), None); +} + +#[test] +fn param_i64() { + let uri = "https://example.com/path?param1=42¶m2=invalid" + .parse() + .unwrap(); + let extractor = UrlExtract::new(&uri); + + assert_eq!(extractor.param_i64("param1"), Some(42)); + assert_eq!(extractor.param_i64("param2"), None); + assert_eq!(extractor.param_i64("nonexistent"), None); +} + +#[test] +fn param_f64() { + let uri = "https://example.com/path?param1=3.14¶m2=invalid" + .parse() + .unwrap(); + let extractor = UrlExtract::new(&uri); + + assert_eq!(extractor.param_f64("param1"), Some(3.14)); + assert_eq!(extractor.param_f64("param2"), None); + assert_eq!(extractor.param_f64("nonexistent"), None); +} + +#[test] +fn url_i64() { + let uri = "https://example.com/path/42/rest".parse().unwrap(); + assert_eq!(UrlExtract::url_i64(&uri, "/path/"), Some(42)); + + let uri_without_match = "https://example.com/otherpath/42/rest".parse().unwrap(); + assert_eq!(UrlExtract::url_i64(&uri_without_match, "/path/"), None); +}