use reqwest::{Client, ClientBuilder};
use std::sync::Arc;
use std::time::Duration;
use crate::types::{Config, Error};
use crate::types::error::Result;
#[derive(Clone)]
pub struct HttpClient {
inner: Arc<Client>,
config: Arc<Config>,
}
impl HttpClient {
pub fn new(config: Config) -> Result<Self> {
let client = Self::build_client(&config)?;
Ok(Self {
inner: Arc::new(client),
config: Arc::new(config),
})
}
fn build_client(config: &Config) -> Result<Client> {
let mut builder = ClientBuilder::new()
.user_agent(&config.fetch.user_agent)
.timeout(Duration::from_millis(config.fetch.total_timeout_ms))
.connect_timeout(Duration::from_millis(config.fetch.connect_timeout_ms))
.pool_max_idle_per_host(10)
.pool_idle_timeout(Duration::from_secs(90))
.tcp_nodelay(true)
.tcp_keepalive(Duration::from_secs(60));
if config.fetch.follow_redirects {
builder = builder.redirect(reqwest::redirect::Policy::limited(
config.fetch.max_redirects as usize,
));
} else {
builder = builder.redirect(reqwest::redirect::Policy::none());
}
if config.fetch.enable_decompression {
builder = builder
.gzip(true)
.brotli(true)
.deflate(true);
} else {
builder = builder
.gzip(false)
.brotli(false)
.deflate(false);
}
builder.build().map_err(Error::Network)
}
pub fn client(&self) -> &Client {
&self.inner
}
pub fn config(&self) -> &Config {
&self.config
}
pub fn user_agent(&self) -> &str {
&self.config.fetch.user_agent
}
}