1use super::interface::ApiInterface;
2use anyhow::{Context, Result};
3use reqwest::{
4 Method,
5 header::{HeaderName, HeaderValue},
6};
7use reqwest_middleware::ClientWithMiddleware;
8use serde::{Serialize, de::DeserializeOwned};
9use std::collections::HashMap;
10use std::fmt::Display;
11
12pub struct ApiClient<T: ApiInterface> {
17 pub(super) interface: T,
18 pub(super) http_client: ClientWithMiddleware,
19}
20unsafe impl<T: ApiInterface> Send for ApiClient<T> {}
21unsafe impl<T: ApiInterface> Sync for ApiClient<T> {}
22
23impl<T: ApiInterface> ApiClient<T> {
24 pub async fn request<
28 R: DeserializeOwned,
29 E: Display,
30 HK: Into<HeaderName>,
31 HV: Into<HeaderValue>,
32 P: Serialize,
33 B: Serialize,
34 >(
35 &self,
36 endpoint: E,
37 method: Method,
38 headers: HashMap<HK, HV>,
39 params: Option<P>,
40 body: Option<B>,
41 ) -> Result<R> {
42 let request = self.interface.build_request(
43 self.http_client.clone(),
44 endpoint,
45 method,
46 headers,
47 params,
48 body,
49 )?;
50 trace!("Sending request for json response: {request:?}");
51
52 self.http_client
53 .execute(request)
54 .await
55 .context("(JSON) Cannot send request")?
56 .json()
57 .await
58 .context("(JSON) Cannot decode request")
59 }
60
61 pub async fn string_request<
64 E: Display,
65 HK: Into<HeaderName>,
66 HV: Into<HeaderValue>,
67 P: Serialize,
68 B: Serialize,
69 >(
70 &self,
71 endpoint: E,
72 method: Method,
73 headers: HashMap<HK, HV>,
74 params: Option<P>,
75 body: Option<B>,
76 ) -> Result<String> {
77 let request = self.interface.build_request(
78 self.http_client.clone(),
79 endpoint,
80 method,
81 headers,
82 params,
83 body,
84 )?;
85 trace!("Sending request for text response: {request:?}");
86
87 let response = self
88 .http_client
89 .execute(request)
90 .await
91 .context("(TEXT) Cannot send request")?;
92
93 trace!("Response for text request: {response:?}");
94
95 response
96 .text()
97 .await
98 .context("(TEXT) Cannot decode request")
99 }
100
101 pub async fn simple_get<R: DeserializeOwned, E: Display>(&self, endpoint: E) -> Result<R> {
103 self.request(
104 endpoint,
105 Method::GET,
106 HashMap::<HeaderName, HeaderValue>::new(),
107 None::<()>,
108 None::<()>,
109 )
110 .await
111 }
112 pub async fn get_params<R: DeserializeOwned, E: Display, P: Serialize>(
114 &self,
115 endpoint: E,
116 params: P,
117 ) -> Result<R> {
118 self.request(
119 endpoint,
120 Method::GET,
121 HashMap::<HeaderName, HeaderValue>::new(),
122 Some(params),
123 None::<()>,
124 )
125 .await
126 }
127
128 pub async fn simple_post<R: DeserializeOwned, E: Display, B: Serialize>(
130 &self,
131 endpoint: E,
132 body: B,
133 ) -> Result<R> {
134 self.request(
135 endpoint,
136 Method::POST,
137 HashMap::<HeaderName, HeaderValue>::new(),
138 None::<()>,
139 Some(body),
140 )
141 .await
142 }
143 pub async fn post_params<R: DeserializeOwned, E: Display, P: Serialize, B: Serialize>(
145 &self,
146 endpoint: E,
147 params: P,
148 body: B,
149 ) -> Result<R> {
150 self.request(
151 endpoint,
152 Method::POST,
153 HashMap::<HeaderName, HeaderValue>::new(),
154 Some(params),
155 Some(body),
156 )
157 .await
158 }
159}