use anyhow::{anyhow, Result};
use reqwest;
use serde_json::Value;
use std::collections::HashMap;
use std::thread;
use tokio::time::{self, Duration};
use urlencoding::encode;
use xmltojson::to_json;
pub type Params = HashMap<String, String>;
pub async fn get_json_resp(url: &str, api_key: &str) -> Result<Value> {
let mut resp;
loop {
let client = get_req_builder(url, api_key);
resp = client.send().await?;
if resp.status() == 202 {
time::sleep(Duration::from_secs(1)).await;
} else {
break;
}
}
let data = resp.text().await?;
let ret = match to_json(&data) {
Ok(res) => res,
Err(_) => return Err(anyhow!("Failed to convert to JSON")),
};
return Ok(ret);
}
pub fn get_json_resp_b(url: &str, api_key: &str) -> Result<Value> {
let mut resp;
loop {
let client = get_req_builder_b(url, api_key);
resp = client.send()?;
if resp.status() == 202 {
thread::sleep(Duration::from_secs(1));
} else {
break;
}
}
let data = resp.text()?;
let ret = match to_json(&data) {
Ok(res) => res,
Err(_) => {
return Err(anyhow!("Failed to convert to JSON"));
}
};
return Ok(ret);
}
pub fn params2qs(params: &Params) -> String {
let mut parts = vec![];
for (k, v) in params {
let mut tmp = String::new();
tmp += &encode(k).to_owned();
tmp.push_str("=");
tmp += &encode(v).to_owned();
parts.push(tmp);
}
return parts.join("&");
}
pub fn get_opts(options: Option<Params>) -> Params {
let mut opts = Params::new();
if let Some(o) = options {
opts = o;
}
return opts;
}
pub fn get_req_builder(url: &str, api_key: &str) -> reqwest::RequestBuilder {
let client = reqwest::Client::new();
return client
.get(url)
.bearer_auth(api_key);
}
pub fn get_req_builder_b(url: &str, api_key: &str) -> reqwest::blocking::RequestBuilder {
let client = reqwest::blocking::Client::new();
return client
.get(url)
.bearer_auth(api_key);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_opts() {
let res = get_opts(None);
assert_eq!(res, Params::new());
let p = Params::from([("key".into(), "value".into())]);
let res = get_opts(Some(p));
assert_eq!(res.len(), 1);
assert!(res.contains_key("key".into()));
}
#[test]
fn test_params_encoding() {
let p = Params::from([("key".into(), "value".into())]);
assert_eq!(params2qs(&p), "key=value");
let p = Params::from([("key=".into(), "value".into())]);
assert_eq!(params2qs(&p), "key%3D=value");
let p = Params::from([
("key1".into(), "value1".into()),
("key2".into(), "value2".into()),
]);
let res = params2qs(&p);
let amp_count = res.chars().filter(|c| *c == '&').count();
assert_eq!(amp_count, 1);
assert!(res.contains("key1=value1"));
assert!(res.contains("key2=value2"));
}
}