http_api_isahc_client/
lib.rs

1pub use http_api_client;
2pub use isahc;
3
4use core::time::Duration;
5
6pub use http_api_client::Client;
7#[cfg(any(
8    feature = "with-sleep-via-tokio",
9    feature = "with-sleep-via-async-timer",
10    feature = "with-sleep-via-async-io"
11))]
12pub use http_api_client::RetryableClient;
13use http_api_client::{async_trait, Body, Request, Response};
14use isahc::{
15    config::Configurable as _, AsyncReadResponseExt as _, Error as IsahcError,
16    HttpClient as IsahcHttpClient,
17};
18
19#[derive(Debug, Clone)]
20pub struct IsahcClient {
21    pub http_client: IsahcHttpClient,
22    pub body_buf_default_capacity: usize,
23}
24
25impl IsahcClient {
26    pub fn new() -> Result<Self, IsahcError> {
27        Ok(Self::with(
28            IsahcHttpClient::builder()
29                .connect_timeout(Duration::from_secs(5))
30                .timeout(Duration::from_secs(30))
31                .build()?,
32        ))
33    }
34
35    pub fn with(http_client: IsahcHttpClient) -> Self {
36        Self {
37            http_client,
38            body_buf_default_capacity: 4 * 1024,
39        }
40    }
41}
42
43#[async_trait]
44impl Client for IsahcClient {
45    type RespondError = IsahcError;
46
47    async fn respond(&self, request: Request<Body>) -> Result<Response<Body>, Self::RespondError> {
48        let res = self.http_client.send_async(request).await?;
49        let (head, body) = res.into_parts();
50
51        let mut body_buf = Vec::with_capacity(
52            body.len().unwrap_or(self.body_buf_default_capacity as u64) as usize,
53        );
54
55        let mut res = Response::from_parts(head, body);
56        res.copy_to(&mut body_buf).await?;
57
58        let (head, _) = res.into_parts();
59        let res = Response::from_parts(head, body_buf);
60
61        Ok(res)
62    }
63}
64
65#[cfg(all(
66    feature = "with-sleep-via-tokio",
67    not(feature = "with-sleep-via-async-timer"),
68    not(feature = "with-sleep-via-async-io")
69))]
70#[async_trait]
71impl RetryableClient for IsahcClient {
72    async fn sleep(&self, dur: Duration) {
73        async_sleep::sleep::<async_sleep::impl_tokio::Sleep>(dur).await;
74    }
75}
76
77#[cfg(all(
78    not(feature = "with-sleep-via-tokio"),
79    feature = "with-sleep-via-async-timer",
80    not(feature = "with-sleep-via-async-io")
81))]
82#[async_trait]
83impl RetryableClient for IsahcClient {
84    async fn sleep(&self, dur: Duration) {
85        async_sleep::sleep::<async_sleep::impl_async_timer::PlatformTimer>(dur).await;
86    }
87}
88
89#[cfg(all(
90    not(feature = "with-sleep-via-tokio"),
91    not(feature = "with-sleep-via-async-timer"),
92    feature = "with-sleep-via-async-io"
93))]
94#[async_trait]
95impl RetryableClient for IsahcClient {
96    async fn sleep(&self, dur: Duration) {
97        async_sleep::sleep::<async_sleep::impl_async_io::Timer>(dur).await;
98    }
99}