Skip to main content

muffy/http_client/
reqwest.rs

1use super::{BareHttpClient, BareRequest, BareResponse, HttpClientError};
2use async_trait::async_trait;
3use log::trace;
4use reqwest::{Client, ClientBuilder, redirect::Policy};
5
6/// An HTTP client based on [`reqwest`].
7#[derive(Debug, Default)]
8pub struct ReqwestHttpClient {
9    client: Client,
10}
11
12impl ReqwestHttpClient {
13    /// Creates an HTTP client.
14    pub fn new() -> Result<Self, reqwest::Error> {
15        Ok(Self {
16            client: ClientBuilder::new()
17                .tcp_keepalive(None)
18                .redirect(Policy::none())
19                .build()?,
20        })
21    }
22}
23
24#[async_trait]
25impl BareHttpClient for ReqwestHttpClient {
26    async fn get(&self, request: &BareRequest) -> Result<BareResponse, HttpClientError> {
27        trace!("sending a request to {}", &request.url);
28
29        let response = self
30            .client
31            .execute(
32                self.client
33                    .get(request.url.clone())
34                    .headers(request.headers.clone())
35                    .build()?,
36            )
37            .await?;
38
39        trace!("got {} response from {}", response.status(), &request.url);
40
41        Ok(BareResponse {
42            url: response.url().clone(),
43            status: response.status(),
44            headers: response.headers().clone(),
45            body: response.bytes().await?.to_vec(),
46        })
47    }
48}
49
50impl From<reqwest::Error> for HttpClientError {
51    fn from(error: reqwest::Error) -> Self {
52        Self::Http(error.to_string().into())
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn create() {
62        ReqwestHttpClient::new().unwrap();
63    }
64}