Skip to main content

bolt_web/
client.rs

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}