bolt_web/
client.rs

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