1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
use api::models::{RequestError, Response}; use api::Result; use reqwest::header::{HeaderMap, HeaderValue}; use reqwest::{RequestBuilder, Url}; use serde::de::DeserializeOwned; use serde::ser::Serialize; use serde_json::{from_str, from_value, to_string}; use std::borrow::Borrow; use std::collections::HashMap; #[derive(Clone, Debug)] pub struct Client { pub host: String, client: ::reqwest::Client, headers: HeaderMap, } impl Client { pub fn new(host: &str) -> Client { let mut headers = HeaderMap::new(); headers.insert("content-type", HeaderValue::from_static("application/json")); Client { host: host.to_owned(), client: ::reqwest::Client::new(), headers, } } pub fn get<T: DeserializeOwned>(&self, endpoint: &str) -> Result<T> { let url = Url::parse(&format!("{}{}", self.host, endpoint))?; self.internal_get(&url) } pub fn get_with_params<T, I, K, V>(&self, endpoint: &str, parameters: I) -> Result<T> where T: DeserializeOwned, I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef<str>, V: AsRef<str>, { let url = Url::parse_with_params(&format!("{}{}", self.host, endpoint), parameters)?; self.internal_get(&url) } pub fn post<T, V>(&self, endpoint: &str, payload: Option<HashMap<&str, V>>) -> Result<T> where T: DeserializeOwned, V: Serialize, { let url = Url::parse(&format!("{}{}", self.host, endpoint))?; self.internal_post(&url, payload) } pub fn post_with_params<T, H, I, K, V>( &self, endpoint: &str, payload: Option<HashMap<&str, H>>, parameters: I, ) -> Result<T> where T: DeserializeOwned, H: Serialize, I: IntoIterator, I::Item: Borrow<(K, V)>, K: AsRef<str>, V: AsRef<str>, { let url = Url::parse_with_params(&format!("{}{}", self.host, endpoint), parameters)?; self.internal_post(&url, payload) } fn internal_get<T: DeserializeOwned>(&self, url: &Url) -> Result<T> { let builder = self.client.get(url.as_str()); self.send(builder) } fn internal_post<T, V>(&self, url: &Url, payload: Option<HashMap<&str, V>>) -> Result<T> where T: DeserializeOwned, V: Serialize, { let builder = self.client.post(url.as_str()); let body = payload.map_or_else(|| Ok(String::default()), |v| to_string(&v)); self.send(builder.body(body?)) } fn send<T: DeserializeOwned>(&self, builder: RequestBuilder) -> Result<T> { let response = builder.headers(self.headers.clone()).send()?.text()?; let value: serde_json::Value = from_str(&response)?; let parsed = from_value::<Response<T>>(value.clone()); match parsed { Ok(item) => Ok(item), Err(_) => { let request_error = from_value::<RequestError>(value)?; Err(request_error.into()) } } } }