#![allow(unused_results)]
use reqwest::Url;
#[inline]
pub fn is_root(url: &Url) -> bool {
!url.path_segments().unwrap().any(|x| !x.is_empty())
}
#[inline]
pub fn extend<I>(mut url: Url, segments: I) -> Url
where
I: IntoIterator,
I::Item: AsRef<str>,
{
url.path_segments_mut()
.unwrap()
.pop_if_empty()
.extend(segments);
url
}
#[inline]
pub fn pop(mut url: Url) -> Url {
url.path_segments_mut()
.expect("Invalid URL")
.pop_if_empty()
.pop()
.pop_if_empty()
.push("");
url
}
pub fn merge(dest: &mut Url, src: &Url) {
dest.set_scheme(src.scheme()).unwrap();
dest.set_host(src.host_str()).unwrap();
dest.set_port(src.port()).unwrap();
let existing: Vec<String> = dest
.path_segments()
.unwrap()
.map(|segment| {
percent_encoding::percent_decode_str(segment)
.decode_utf8_lossy()
.into_owned()
})
.collect();
dest.path_segments_mut()
.unwrap()
.clear()
.extend(src.path_segments().unwrap())
.pop_if_empty()
.extend(existing);
}
#[cfg(test)]
mod test {
use reqwest::Url;
use super::*;
#[test]
fn test_is_root() {
assert!(is_root(&Url::parse("https://example.com").unwrap()));
assert!(is_root(&Url::parse("https://example.com/").unwrap()));
}
#[test]
fn test_is_not_root() {
assert!(!is_root(&Url::parse("https://example.com/v1/").unwrap()));
assert!(!is_root(
&Url::parse("https://example.com/v2/project_id").unwrap()
));
}
#[test]
fn test_pop() {
assert_eq!(
pop(Url::parse("https://example.com/v1").unwrap()).as_str(),
"https://example.com/"
);
assert_eq!(
pop(Url::parse("https://example.com/v1/").unwrap()).as_str(),
"https://example.com/"
);
assert_eq!(
pop(Url::parse("https://example.com/v1/foobar").unwrap()).as_str(),
"https://example.com/v1/"
);
assert_eq!(
pop(Url::parse("https://example.com/v1/foobar/").unwrap()).as_str(),
"https://example.com/v1/"
);
}
#[test]
fn test_merge_host_only() {
let mut dest = Url::parse("http://compute").unwrap();
let src = Url::parse("https://example.com").unwrap();
merge(&mut dest, &src);
assert_eq!(dest.as_str(), "https://example.com/");
}
#[test]
fn test_merge_with_port() {
let mut dest = Url::parse("http://compute").unwrap();
let src = Url::parse("https://example.com:5050").unwrap();
merge(&mut dest, &src);
assert_eq!(dest.as_str(), "https://example.com:5050/");
}
#[test]
fn test_merge_existing_path() {
let mut dest = Url::parse("http://compute/path/1").unwrap();
let src = Url::parse("https://example.com").unwrap();
merge(&mut dest, &src);
assert_eq!(dest.as_str(), "https://example.com/path/1");
}
#[test]
fn test_merge_new_path() {
let mut dest = Url::parse("http://compute").unwrap();
let src = Url::parse("https://example.com/compute").unwrap();
merge(&mut dest, &src);
assert_eq!(dest.as_str(), "https://example.com/compute/");
}
#[test]
fn test_merge_combine_args() {
let mut dest = Url::parse("http://compute/?answer=42").unwrap();
let src = Url::parse("https://example.com").unwrap();
merge(&mut dest, &src);
assert_eq!(dest.as_str(), "https://example.com/?answer=42");
}
#[test]
fn test_merge_combine_path() {
let mut dest = Url::parse("http://compute/path/1").unwrap();
let src = Url::parse("https://example.com/compute").unwrap();
merge(&mut dest, &src);
assert_eq!(dest.as_str(), "https://example.com/compute/path/1");
}
#[test]
fn test_merge_combine_everything() {
let mut dest = Url::parse("http://compute/path/1/?foo=bar,answer=42").unwrap();
let src = Url::parse("https://example.com:5050/compute/").unwrap();
merge(&mut dest, &src);
assert_eq!(
dest.as_str(),
"https://example.com:5050/compute/path/1/?foo=bar,answer=42"
);
}
#[test]
fn test_merge_with_percent_encoded_segments() {
let mut dest = Url::parse("http://compute/path%2Fto/foo%20bar").unwrap();
let src = Url::parse("https://example.com:5050/compute/").unwrap();
merge(&mut dest, &src);
assert_eq!(
dest.as_str(),
"https://example.com:5050/compute/path%2Fto/foo%20bar"
);
}
}