use axum::http::{uri, Uri}; pub fn uri_with_path(uri: &Uri, path: &str) -> Uri { if path.starts_with('/') { // 'path' is an root path, so let's just override the uri's path return uri::Builder::new() .scheme(uri.scheme_str().unwrap()) .authority(uri.authority().unwrap().as_str()) .path_and_query(path) .build() .unwrap(); } // 'path' is a relative/local path, so let's combine it with the uri's path let base_path = uri.path_and_query().map_or("/", |p| p.path()); if base_path.ends_with('/') { return uri::Builder::new() .scheme(uri.scheme_str().unwrap()) .authority(uri.authority().unwrap().as_str()) .path_and_query(format!("{base_path}{path}")) .build() .unwrap(); } let (base, _) = base_path.rsplit_once('/').unwrap(); return uri::Builder::new() .scheme(uri.scheme_str().unwrap()) .authority(uri.authority().unwrap().as_str()) .path_and_query(format!("{base}/{path}")) .build() .unwrap(); } #[cfg(test)] mod tests { use axum::http::Uri; use crate::helpers::uri_with_path; #[test] fn uri_with_relative_path() { let uri: Uri = "http://localhost/baba/".parse().unwrap(); assert_eq!(uri_with_path(&uri, "is/you").to_string(), "http://localhost/baba/is/you"); } #[test] fn uri_with_absolute_path() { let uri: Uri = "http://localhost/baba/is/you".parse().unwrap(); assert_eq!(uri_with_path(&uri, "/keke/is/move").to_string(), "http://localhost/keke/is/move"); } #[test] fn uri_with_index_relative_path() { let uri: Uri = "http://localhost/baba/is/you".parse().unwrap(); assert_eq!(uri_with_path(&uri, "happy").to_string(), "http://localhost/baba/is/happy"); } }