diff --git a/src/http.rs b/src/http.rs index 1d7c674..8eff4ce 100644 --- a/src/http.rs +++ b/src/http.rs @@ -62,7 +62,16 @@ pub fn build_request( #[instrument(skip(query), err)] pub fn build_url(base: &str, path: &str, query: Option) -> Result { let mut url = Url::parse(base).map_err(|e| ClientError::UrlParseError { source: e })?; - url.path_segments_mut().unwrap().extend(path.split('/')); + + // remove leading `/` from path to avoid double `//` when base has a path + let path = path.strip_prefix('/').unwrap_or(path); + + url.path_segments_mut() + .unwrap() + // avoids double `//` when base path has trailing slash + .pop_if_empty() + .extend(path.split('/')); + if let Some(q) = query { url.set_query(Some(q.as_str())); } @@ -71,3 +80,62 @@ pub fn build_url(base: &str, path: &str, query: Option) -> Result() .map_err(|e| ClientError::UrlBuildError { source: e }) } + +#[cfg(test)] +mod test { + use super::build_url; + + #[test] + fn build_url_path_with_trailing_slash() { + let url = build_url("https://192.0.2.2", "foobar/", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/foobar/"); + } + + #[test] + fn build_url_base_without_path_and_path_without_slash() { + let url = build_url("https://192.0.2.2", "foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/foobar"); + } + + #[test] + fn build_url_base_without_path_and_path_with_slash() { + let url = build_url("https://192.0.2.2", "/foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/foobar"); + } + + #[test] + fn build_url_base_with_trailing_slash_and_path_without_slash() { + let url = build_url("https://192.0.2.2/", "foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/foobar"); + } + + #[test] + fn build_url_base_with_trailing_slash_and_path_with_slash() { + let url = build_url("https://192.0.2.2/", "/foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/foobar"); + } + + #[test] + fn build_url_base_with_path_and_path_without_slash() { + let url = build_url("https://192.0.2.2/base/path", "foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/base/path/foobar"); + } + + #[test] + fn build_url_base_with_path_and_path_with_slash() { + let url = build_url("https://192.0.2.2/base/path", "/foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/base/path/foobar"); + } + + #[test] + fn build_url_base_with_path_and_trailing_slash_and_path_without_slash() { + let url = build_url("https://192.0.2.2/base/path/", "foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/base/path/foobar"); + } + + #[test] + fn build_url_base_with_path_and_trailing_slash_and_path_with_slash() { + let url = build_url("https://192.0.2.2/base/path/", "/foobar", None).unwrap(); + assert_eq!(url.to_string(), "https://192.0.2.2/base/path/foobar"); + } +}