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