Skip to main content

picdl_rs/http/
reqwest.rs

1use reqwest::{Client, Method};
2
3use super::client::{Headers, HttpClient, Query};
4
5/// Reqwest implementation of HttpClient
6#[derive(Debug, Clone)]
7pub struct ReqwestClient {
8    client: Client
9}
10
11/// Enum of possible HTTP errors
12#[derive(Debug)]
13pub enum ReqwestError {
14    Client(reqwest::Error),
15    StatusCode(reqwest::Response),
16}
17
18/// Implementation of Default for ReqwestClient.
19impl Default for ReqwestClient {
20    fn default() -> Self {
21        let client = reqwest::ClientBuilder::new()
22            .build()
23            .unwrap();
24        Self { client }
25    }
26}
27
28/// Implements conversion of reqwest::Error to ReqwestError
29impl From<reqwest::Error> for ReqwestError {
30    fn from(value: reqwest::Error) -> Self {
31        ReqwestError::Client(value)
32    }
33}
34
35/// Only implements `request` function for internal
36/// usage in ReqwestClient
37impl ReqwestClient {
38
39    /// Internal function to remove the sending request
40    /// overhead from `get` and `post` functions 
41    #[inline]
42    async fn request(
43        &self,
44        payload: &Query,
45        headers: &Headers,
46        url: String,
47        method: Method
48    ) -> Result<String, ReqwestError> {
49        let mut request = self.client.request(method, url);
50        request = request
51            .query(payload)
52            .headers(headers.try_into().unwrap()) // Should not fail; converting from a
53                                                  // HashMap<String, String> to a HeaderMap which
54                                                  // is technically the same
55            .header("Content-Type", "application/json");
56
57        let response = request.send().await?;
58
59        Ok(response.text().await?)
60    }
61}
62
63/// Implements all functions of HttpClient for reqwest
64impl HttpClient for ReqwestClient {
65    /// Error type for a HTTP client
66    /// Typically should be an enum of client errors
67    ///
68    /// # Example
69    /// ```no_run
70    /// #[derive(Debug)]
71    /// pub enum ReqwestError {
72    ///     Client(reqwest::Error),
73    ///     StatusCode(reqwest::Response),
74    /// }
75    /// ```
76    type Error = ReqwestError;
77
78    /// GET function that implements a GET request in a specific HTTP client,
79    /// such as reqwest
80    #[inline]
81    async fn get(
82        &self,
83        url: String,
84        headers: &Headers,
85        payload: &Query,
86    ) -> Result<String, Self::Error> {
87        self.request(payload, headers, url, Method::GET).await
88    }
89
90    /// POST function that implements a POST request in a specific HTTP client,
91    /// such as reqwest
92    #[inline]
93    async fn post(
94        &self,
95        url: String,
96        headers: &Headers,
97        payload: &Query,
98    ) -> Result<String, Self::Error> {
99        self.request(payload, headers, url, Method::POST).await
100    }
101}
102