halldyll_core/fetch/
client.rs1use reqwest::{Client, ClientBuilder};
4use std::sync::Arc;
5use std::time::Duration;
6
7use crate::types::{Config, Error};
8use crate::types::error::Result;
9
10#[derive(Clone)]
12pub struct HttpClient {
13 inner: Arc<Client>,
14 config: Arc<Config>,
15}
16
17impl HttpClient {
18 pub fn new(config: Config) -> Result<Self> {
20 let client = Self::build_client(&config)?;
21 Ok(Self {
22 inner: Arc::new(client),
23 config: Arc::new(config),
24 })
25 }
26
27 fn build_client(config: &Config) -> Result<Client> {
29 let mut builder = ClientBuilder::new()
30 .user_agent(&config.fetch.user_agent)
31 .timeout(Duration::from_millis(config.fetch.total_timeout_ms))
32 .connect_timeout(Duration::from_millis(config.fetch.connect_timeout_ms))
33 .pool_max_idle_per_host(10)
34 .pool_idle_timeout(Duration::from_secs(90))
35 .tcp_nodelay(true)
36 .tcp_keepalive(Duration::from_secs(60));
37
38 if config.fetch.follow_redirects {
40 builder = builder.redirect(reqwest::redirect::Policy::limited(
41 config.fetch.max_redirects as usize,
42 ));
43 } else {
44 builder = builder.redirect(reqwest::redirect::Policy::none());
45 }
46
47 if config.fetch.enable_decompression {
49 builder = builder
50 .gzip(true)
51 .brotli(true)
52 .deflate(true);
53 } else {
54 builder = builder
55 .gzip(false)
56 .brotli(false)
57 .deflate(false);
58 }
59
60 builder.build().map_err(Error::Network)
61 }
62
63 pub fn client(&self) -> &Client {
65 &self.inner
66 }
67
68 pub fn config(&self) -> &Config {
70 &self.config
71 }
72
73 pub fn user_agent(&self) -> &str {
75 &self.config.fetch.user_agent
76 }
77}