ollama_oxide/http/client_config.rs
1//! HTTP client configuration
2
3use std::time::Duration;
4
5use crate::{Error, Result};
6use url::Url;
7
8/// Validates that a URL is well-formed and uses http or https scheme
9fn validate_base_url(base_url: &str) -> Result<()> {
10 let url = Url::parse(base_url)?;
11 if url.scheme() != "http" && url.scheme() != "https" {
12 return Err(Error::InvalidUrlError(
13 url::ParseError::RelativeUrlWithoutBase,
14 ));
15 }
16 Ok(())
17}
18
19/// Configuration for Ollama HTTP client
20///
21/// This struct allows customization of the HTTP client behavior including
22/// base URL, timeout, and retry settings. All constructors validate that
23/// the base URL is well-formed and uses http or https scheme.
24///
25/// # Examples
26///
27/// ```no_run
28/// use ollama_oxide::ClientConfig;
29/// use std::time::Duration;
30///
31/// // Use default configuration (http://localhost:11434)
32/// let config = ClientConfig::default();
33///
34/// // Custom configuration
35/// let config = ClientConfig::new(
36/// "http://example.com:8080".to_string(),
37/// Duration::from_secs(60),
38/// 5,
39/// )?;
40///
41/// // Just a custom URL
42/// let config = ClientConfig::with_base_url("http://example.com:8080".to_string())?;
43/// # Ok::<(), ollama_oxide::Error>(())
44/// ```
45#[derive(Debug, Clone)]
46pub struct ClientConfig {
47 /// Base URL for Ollama API (validated: must be http or https)
48 base_url: String,
49
50 /// Request timeout duration
51 timeout: Duration,
52
53 /// Maximum retry attempts on failure (0 = no retries)
54 max_retries: u32,
55}
56
57impl Default for ClientConfig {
58 fn default() -> Self {
59 Self {
60 base_url: "http://localhost:11434".to_string(),
61 timeout: Duration::from_secs(30),
62 max_retries: 3,
63 }
64 }
65}
66
67impl ClientConfig {
68 /// Creates a new `ClientConfig` with all attributes specified.
69 ///
70 /// # Errors
71 ///
72 /// Returns an error if the base URL is invalid or uses an unsupported scheme.
73 ///
74 /// # Examples
75 ///
76 /// ```no_run
77 /// use ollama_oxide::ClientConfig;
78 /// use std::time::Duration;
79 ///
80 /// let config = ClientConfig::new(
81 /// "http://example.com:8080".to_string(),
82 /// Duration::from_secs(60),
83 /// 5,
84 /// )?;
85 /// # Ok::<(), ollama_oxide::Error>(())
86 /// ```
87 pub fn new(base_url: String, timeout: Duration, max_retries: u32) -> Result<Self> {
88 validate_base_url(&base_url)?;
89 Ok(Self {
90 base_url,
91 timeout,
92 max_retries,
93 })
94 }
95
96 /// Creates a new `ClientConfig` with only `base_url`, using defaults for `timeout` (30s) and `max_retries` (3).
97 ///
98 /// # Errors
99 ///
100 /// Returns an error if the base URL is invalid or uses an unsupported scheme.
101 ///
102 /// # Examples
103 ///
104 /// ```no_run
105 /// use ollama_oxide::ClientConfig;
106 ///
107 /// let config = ClientConfig::with_base_url("http://example.com:8080".to_string())?;
108 /// assert_eq!(config.timeout(), std::time::Duration::from_secs(30));
109 /// assert_eq!(config.max_retries(), 3);
110 /// # Ok::<(), ollama_oxide::Error>(())
111 /// ```
112 pub fn with_base_url(base_url: String) -> Result<Self> {
113 validate_base_url(&base_url)?;
114 Ok(Self {
115 base_url,
116 ..Self::default()
117 })
118 }
119
120 /// Creates a new `ClientConfig` with `base_url` and `timeout`, using the default `max_retries` (3).
121 ///
122 /// # Errors
123 ///
124 /// Returns an error if the base URL is invalid or uses an unsupported scheme.
125 ///
126 /// # Examples
127 ///
128 /// ```no_run
129 /// use ollama_oxide::ClientConfig;
130 /// use std::time::Duration;
131 ///
132 /// let config = ClientConfig::with_base_url_and_timeout(
133 /// "http://example.com:8080".to_string(),
134 /// Duration::from_secs(60),
135 /// )?;
136 /// assert_eq!(config.max_retries(), 3);
137 /// # Ok::<(), ollama_oxide::Error>(())
138 /// ```
139 pub fn with_base_url_and_timeout(base_url: String, timeout: Duration) -> Result<Self> {
140 validate_base_url(&base_url)?;
141 Ok(Self {
142 base_url,
143 timeout,
144 ..Self::default()
145 })
146 }
147
148 /// Returns the base URL
149 #[inline]
150 pub fn base_url(&self) -> &str {
151 &self.base_url
152 }
153
154 /// Returns the request timeout duration
155 #[inline]
156 pub fn timeout(&self) -> Duration {
157 self.timeout
158 }
159
160 /// Returns the maximum retry attempts
161 #[inline]
162 pub fn max_retries(&self) -> u32 {
163 self.max_retries
164 }
165
166 /// Build full URL from base URL and endpoint path
167 ///
168 /// # Examples
169 ///
170 /// ```no_run
171 /// use ollama_oxide::ClientConfig;
172 ///
173 /// let config = ClientConfig::default();
174 /// let url = config.url("/api/version");
175 /// assert_eq!(url, "http://localhost:11434/api/version");
176 /// ```
177 #[inline]
178 pub fn url(&self, endpoint: &str) -> String {
179 format!("{}{}", self.base_url, endpoint)
180 }
181}