1use super::config::XHttpConfig;
17use crate::xutil;
18use std::sync::OnceLock;
19use std::time::Duration;
20
21pub(crate) static HTTP_CLIENT: OnceLock<reqwest::Client> = OnceLock::new();
23
24pub fn c() -> &'static reqwest::Client {
29 HTTP_CLIENT.get_or_init(|| {
30 xutil::warn_if_enable_debug(
31 "XHttp client accessed before init, using default configuration",
32 );
33 reqwest::Client::new()
34 })
35}
36
37pub fn build_client(config: &XHttpConfig) -> Result<reqwest::Client, crate::error::XOneError> {
41 let timeout = duration_or(&config.timeout, Duration::from_secs(30));
42 let connect_timeout = duration_or(&config.dial_timeout, Duration::from_secs(10));
43 let keep_alive = duration_or(&config.dial_keep_alive, Duration::from_secs(30));
44
45 let builder = reqwest::Client::builder()
46 .timeout(timeout)
47 .connect_timeout(connect_timeout)
48 .pool_max_idle_per_host(config.pool_max_idle_per_host)
49 .tcp_keepalive(keep_alive);
50
51 builder
52 .build()
53 .map_err(|e| crate::error::XOneError::Other(format!("XHttp build client failed: {e}")))
54}
55
56fn duration_or(value: &str, default: Duration) -> Duration {
57 xutil::to_duration(value).unwrap_or(default)
58}
59
60pub fn get(url: &str) -> reqwest::RequestBuilder {
64 c().get(url)
65}
66
67pub fn post(url: &str) -> reqwest::RequestBuilder {
69 c().post(url)
70}
71
72pub fn put(url: &str) -> reqwest::RequestBuilder {
74 c().put(url)
75}
76
77pub fn patch(url: &str) -> reqwest::RequestBuilder {
79 c().patch(url)
80}
81
82pub fn delete(url: &str) -> reqwest::RequestBuilder {
84 c().delete(url)
85}
86
87pub fn head(url: &str) -> reqwest::RequestBuilder {
89 c().head(url)
90}