polyte_gamma/
request.rs

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
10/// Generic request builder for Gamma API
11pub 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    /// Create a new request
21    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    /// Execute the request and deserialize response
40    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        // Get text for debugging
63        let text = response.text().await?;
64
65        tracing::debug!("Response body: {}", text);
66
67        // Deserialize and provide better error context
68        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    /// Execute the request and return raw response
76    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}