Skip to main content

vtcode_commons/
http.rs

1//! HTTP client utilities
2
3use 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        // Avoid system proxy discovery on macOS because it can panic in restricted environments.
14        builder.no_proxy()
15    }
16    #[cfg(not(target_os = "macos"))]
17    {
18        builder
19    }
20}
21
22fn build_client<F>(configure: F) -> Client
23where
24    F: Fn(ClientBuilder) -> ClientBuilder,
25{
26    let primary_builder = configure(apply_platform_proxy_policy(ClientBuilder::new()));
27    primary_builder.build().unwrap_or_else(|_| {
28        let fallback_builder = apply_platform_proxy_policy(ClientBuilder::new())
29            .timeout(DEFAULT_TIMEOUT)
30            .connect_timeout(SHORT_TIMEOUT);
31        fallback_builder
32            .build()
33            .unwrap_or_else(|e| panic!("failed to build HTTP client: {e}"))
34    })
35}
36
37/// Create a default HTTP client with standard timeouts
38pub fn create_default_client() -> Client {
39    create_client_with_timeout(DEFAULT_TIMEOUT)
40}
41
42/// Create an HTTP client with a custom timeout
43pub fn create_client_with_timeout(timeout: Duration) -> Client {
44    build_client(|builder| builder.timeout(timeout).connect_timeout(SHORT_TIMEOUT))
45}
46
47/// Create an HTTP client with custom connect and request timeouts
48pub fn create_client_with_timeouts(connect_timeout: Duration, request_timeout: Duration) -> Client {
49    build_client(|builder| {
50        builder
51            .timeout(request_timeout)
52            .connect_timeout(connect_timeout)
53    })
54}
55
56/// Create an HTTP client with a specific user agent
57pub fn create_client_with_user_agent(user_agent: &str) -> Client {
58    build_client(|builder| builder.user_agent(user_agent).timeout(DEFAULT_TIMEOUT))
59}
60
61/// Create an HTTP client optimized for streaming
62pub fn create_streaming_client() -> Client {
63    build_client(|builder| {
64        builder
65            .connect_timeout(SHORT_TIMEOUT)
66            .tcp_keepalive(Some(Duration::from_secs(60)))
67    })
68}
69
70/// Get a default client or create one
71pub fn get_or_create_default_client(existing: Option<Client>) -> Client {
72    existing.unwrap_or_else(create_default_client)
73}