pub type QueryParam<'a> = (&'a str, &'a str);
pub type QueryParams<'a> = Vec<QueryParam<'a>>;
pub fn build_querystring(query: QueryParams) -> String {
query.iter().fold(String::new(), |acc, &tuple| {
acc + tuple.0 + "=" + tuple.1 + "&"
})
}
pub struct URLBuilder {
host: String,
path: String,
params: Vec<(String, String)>,
}
pub fn build_url(host: &str, path: &str, params: Vec<Option<(&str, &str)>>) -> String {
let mut url_builder = URLBuilder::new(host);
url_builder.path(path);
for (key, value) in params.iter().filter_map(|x| *x) {
url_builder.param(key, value);
}
url_builder.build()
}
impl URLBuilder {
pub fn new(host: &str) -> URLBuilder {
let host = if host.starts_with("https://") {
host.to_string()
} else {
format!("https://{}", host)
};
let host = if let Some(trimmed) = host.strip_suffix('/') {
trimmed.to_string()
} else {
host
};
URLBuilder {
host: host.to_string(),
params: vec![],
path: "/".to_string(),
}
}
pub fn param(&mut self, key: &str, value: &str) -> &mut Self {
self.params
.push((key.to_owned(), urlencoding::encode(value).to_string()));
self
}
pub fn path(&mut self, path: &str) -> &mut Self {
path.clone_into(&mut self.path);
self
}
pub fn build(self) -> String {
let mut url_params = String::new();
if !self.params.is_empty() {
url_params.push('?');
let qs_args = self.params.iter().map(|(k, v)| (&**k, &**v)).collect();
url_params.push_str(build_querystring(qs_args).as_str());
}
format!("{}{}{}", self.host, self.path, url_params)
}
}