pub use anyhow::{anyhow, Result}; use futures::future::BoxFuture; use isahc::{ config::{Configurable, RedirectPolicy}, AsyncBody, }; pub use isahc::{ http::{Method, Uri}, Error, }; use smol::future::FutureExt; use std::{sync::Arc, time::Duration}; pub use url::Url; pub type Request = isahc::Request; pub type Response = isahc::Response; pub trait HttpClient: Send + Sync { fn send(&self, req: Request) -> BoxFuture>; fn get<'a>( &'a self, uri: &str, body: AsyncBody, follow_redirects: bool, ) -> BoxFuture<'a, Result> { let request = isahc::Request::builder() .redirect_policy(if follow_redirects { RedirectPolicy::Follow } else { RedirectPolicy::None }) .method(Method::GET) .uri(uri) .body(body); match request { Ok(request) => self.send(request), Err(error) => async move { Err(error.into()) }.boxed(), } } } pub fn client() -> Arc { Arc::new( isahc::HttpClient::builder() .connect_timeout(Duration::from_secs(5)) .low_speed_timeout(100, Duration::from_secs(5)) .build() .unwrap(), ) } impl HttpClient for isahc::HttpClient { fn send(&self, req: Request) -> BoxFuture> { Box::pin(async move { self.send_async(req).await }) } }