1use reqwest::{Client, ClientBuilder};
4use std::time::Duration;
5
6pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(30);
7pub const SHORT_TIMEOUT: Duration = Duration::from_secs(5);
8pub const LONG_TIMEOUT: Duration = Duration::from_secs(300);
9
10fn apply_platform_proxy_policy(builder: ClientBuilder) -> ClientBuilder {
11 #[cfg(target_os = "macos")]
12 {
13 builder.no_proxy()
15 }
16 #[cfg(not(target_os = "macos"))]
17 {
18 builder
19 }
20}
21
22#[allow(clippy::panic)]
23fn build_client<F>(configure: F) -> Client
24where
25 F: Fn(ClientBuilder) -> ClientBuilder,
26{
27 let primary_builder = configure(apply_platform_proxy_policy(ClientBuilder::new()));
28 primary_builder.build().unwrap_or_else(|_| {
29 let fallback_builder = apply_platform_proxy_policy(ClientBuilder::new())
30 .timeout(DEFAULT_TIMEOUT)
31 .connect_timeout(SHORT_TIMEOUT);
32 fallback_builder
33 .build()
34 .unwrap_or_else(|e| panic!("failed to build HTTP client: {e}"))
35 })
36}
37
38pub fn create_default_client() -> Client {
40 create_client_with_timeout(DEFAULT_TIMEOUT)
41}
42
43pub fn create_client_with_timeout(timeout: Duration) -> Client {
45 build_client(|builder| builder.timeout(timeout).connect_timeout(SHORT_TIMEOUT))
46}
47
48pub fn create_client_with_timeouts(connect_timeout: Duration, request_timeout: Duration) -> Client {
50 build_client(|builder| {
51 builder
52 .timeout(request_timeout)
53 .connect_timeout(connect_timeout)
54 })
55}
56
57pub fn create_client_with_user_agent(user_agent: &str) -> Client {
59 build_client(|builder| builder.user_agent(user_agent).timeout(DEFAULT_TIMEOUT))
60}
61
62pub fn create_streaming_client() -> Client {
64 build_client(|builder| {
65 builder
66 .connect_timeout(SHORT_TIMEOUT)
67 .tcp_keepalive(Some(Duration::from_secs(60)))
68 })
69}
70
71pub fn get_or_create_default_client(existing: Option<Client>) -> Client {
73 existing.unwrap_or_else(create_default_client)
74}