1use bytes::Bytes;
2use http_body_util::{BodyExt, Full};
3use hyper::{Method, Request};
4
5use hyper::http::request::Builder;
6use hyper_tls::HttpsConnector;
7use hyper_util::client::legacy::{Client as HyperClient, connect::HttpConnector};
8use hyper_util::rt::TokioExecutor;
9use serde::Serialize;
10use serde::de::DeserializeOwned;
11use serde_json::Value;
12
13use crate::types::BoltError;
14
15#[derive(Clone)]
16#[allow(dead_code)]
17pub struct Client {
18 client: HyperClient<HttpsConnector<HttpConnector>, Full<Bytes>>,
19}
20
21#[allow(dead_code)]
22impl Client {
23 pub fn new() -> Self {
24 let https = HttpsConnector::new();
25 let client = HyperClient::builder(TokioExecutor::new()).build::<_, Full<Bytes>>(https);
26 Self { client }
27 }
28
29 fn apply_headers(mut builder: Builder, headers: &Option<Value>) -> Builder {
30 if let Some(Value::Object(map)) = headers {
31 for (k, v) in map {
32 if let Some(s) = v.as_str() {
33 builder = builder.header(k, s);
34 }
35 }
36 }
37 builder
38 }
39
40 pub async fn fetch(&self, url: &str, headers: &Option<Value>) -> Result<String, BoltError> {
41 let mut builder = Request::builder().method(Method::GET).uri(url);
42 builder = Self::apply_headers(builder, &headers);
43
44 let req = builder.body(Full::new(Bytes::new()))?;
45 let resp = self.client.request(req).await?;
46 let body = resp.into_body().collect().await?.to_bytes();
47
48 Ok(String::from_utf8_lossy(&body).to_string())
49 }
50
51 async fn send_json<T: Serialize + ?Sized, U: DeserializeOwned>(
52 &self,
53 method: Method,
54 url: &str,
55 body: &T,
56 headers: &Option<Value>,
57 ) -> Result<U, BoltError> {
58 let body_bytes = serde_json::to_vec(body)?;
59
60 let mut builder = Request::builder()
61 .method(method)
62 .uri(url)
63 .header("Content-Type", "application/json");
64
65 builder = Self::apply_headers(builder, &headers);
66
67 let req = builder.body(Full::new(Bytes::from(body_bytes)))?;
68 let resp = self.client.request(req).await?;
69 let bytes = resp.into_body().collect().await?.to_bytes();
70
71 Ok(serde_json::from_slice(&bytes)?)
72 }
73
74 pub async fn get<T: DeserializeOwned>(
75 &self,
76 url: &str,
77 headers: &Option<Value>,
78 ) -> Result<T, BoltError> {
79 let mut builder = Request::builder().method(Method::GET).uri(url);
80 builder = Self::apply_headers(builder, &headers);
81
82 let req = builder.body(Full::new(Bytes::new()))?;
83 let resp = self.client.request(req).await?;
84 let body = resp.into_body().collect().await?.to_bytes();
85
86 Ok(serde_json::from_slice(&body)?)
87 }
88
89 pub async fn post<T: Serialize + ?Sized, U: DeserializeOwned>(
90 &self,
91 url: &str,
92 body: &T,
93 headers: &Option<Value>,
94 ) -> Result<U, BoltError> {
95 self.send_json(Method::POST, url, body, headers).await
96 }
97
98 pub async fn put<T: Serialize + ?Sized, U: DeserializeOwned>(
99 &self,
100 url: &str,
101 body: &T,
102 headers: &Option<Value>,
103 ) -> Result<U, BoltError> {
104 self.send_json(Method::PUT, url, body, headers).await
105 }
106
107 pub async fn patch<T: Serialize + ?Sized, U: DeserializeOwned>(
108 &self,
109 url: &str,
110 body: &T,
111 headers: &Option<Value>,
112 ) -> Result<U, BoltError> {
113 self.send_json(Method::PATCH, url, body, headers).await
114 }
115
116 pub async fn delete<U: DeserializeOwned>(
117 &self,
118 url: &str,
119 headers: &Option<Value>,
120 ) -> Result<U, BoltError> {
121 let mut builder = Request::builder().method(Method::DELETE).uri(url);
122 builder = Self::apply_headers(builder, &headers);
123
124 let req = builder.body(Full::new(Bytes::new()))?;
125
126 let resp = self.client.request(req).await?;
127
128 let body_bytes = resp.into_body().collect().await?.to_bytes();
129
130 Ok(serde_json::from_slice(&body_bytes)?)
131 }
132
133 pub async fn delete_with_payload<T: Serialize + ?Sized, U: DeserializeOwned>(
134 &self,
135 url: &str,
136 body: &T,
137 headers: &Option<Value>,
138 ) -> Result<U, BoltError> {
139 self.send_json(Method::DELETE, url, body, headers).await
140 }
141}