1use std::marker::PhantomData;
2
3pub use polyte_core::request::QueryBuilder;
4use reqwest::{Client, Response};
5use serde::de::DeserializeOwned;
6use url::Url;
7
8use crate::error::{GammaError, Result};
9
10pub struct Request<T> {
12 pub(crate) client: Client,
13 pub(crate) base_url: Url,
14 pub(crate) path: String,
15 pub(crate) query: Vec<(String, String)>,
16 pub(crate) _marker: PhantomData<T>,
17}
18
19impl<T> Request<T> {
20 pub(crate) fn new(client: Client, base_url: Url, path: String) -> Self {
22 Self {
23 client,
24 base_url,
25 path,
26 query: Vec::new(),
27 _marker: PhantomData,
28 }
29 }
30}
31
32impl<T> QueryBuilder for Request<T> {
33 fn add_query(&mut self, key: String, value: String) {
34 self.query.push((key, value));
35 }
36}
37
38impl<T: DeserializeOwned> Request<T> {
39 pub async fn send(self) -> Result<T> {
41 let url = self.base_url.join(&self.path)?;
42
43 let mut request = self.client.get(url);
44
45 if !self.query.is_empty() {
46 request = request.query(&self.query);
47 }
48
49 tracing::debug!("Sending request to: {:?}", request);
50
51 let response = request.send().await?;
52 let status = response.status();
53
54 tracing::debug!("Response status: {}", status);
55
56 if !status.is_success() {
57 let error = GammaError::from_response(response).await;
58 tracing::error!("Request failed: {:?}", error);
59 return Err(error);
60 }
61
62 let text = response.text().await?;
64
65 tracing::debug!("Response body: {}", text);
66
67 serde_json::from_str(&text).map_err(|e| {
69 tracing::error!("Deserialization failed: {}", e);
70 tracing::error!("Failed to deserialize: {}", text);
71 e.into()
72 })
73 }
74
75 pub async fn send_raw(self) -> Result<Response> {
77 let url = self.base_url.join(&self.path)?;
78
79 let mut request = self.client.get(url);
80
81 if !self.query.is_empty() {
82 request = request.query(&self.query);
83 }
84
85 tracing::debug!("Sending request to: {:?}", request);
86
87 let response = request.send().await?;
88 let status = response.status();
89
90 tracing::debug!("Response status: {}", status);
91
92 if !status.is_success() {
93 let error = GammaError::from_response(response).await;
94 tracing::error!("Request failed: {:?}", error);
95 return Err(error);
96 }
97
98 Ok(response)
99 }
100}