firefox_webdriver/browser/
proxy.rs1use serde::{Deserialize, Serialize};
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
31#[serde(rename_all = "lowercase")]
32pub enum ProxyType {
33 Http,
35
36 Https,
38
39 Socks4,
41
42 #[serde(rename = "socks")]
44 Socks5,
45
46 #[default]
48 Direct,
49}
50
51impl ProxyType {
56 #[inline]
58 #[must_use]
59 pub fn as_str(&self) -> &'static str {
60 match self {
61 Self::Http => "http",
62 Self::Https => "https",
63 Self::Socks4 => "socks4",
64 Self::Socks5 => "socks",
65 Self::Direct => "direct",
66 }
67 }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct ProxyConfig {
91 #[serde(rename = "type")]
93 pub proxy_type: ProxyType,
94
95 pub host: String,
97
98 pub port: u16,
100
101 #[serde(skip_serializing_if = "Option::is_none")]
103 pub username: Option<String>,
104
105 #[serde(skip_serializing_if = "Option::is_none")]
107 pub password: Option<String>,
108
109 #[serde(rename = "proxyDns", default)]
111 pub proxy_dns: bool,
112}
113
114impl ProxyConfig {
119 #[must_use]
127 pub fn new(proxy_type: ProxyType, host: impl Into<String>, port: u16) -> Self {
128 Self {
129 proxy_type,
130 host: host.into(),
131 port,
132 username: None,
133 password: None,
134 proxy_dns: false,
135 }
136 }
137
138 #[inline]
140 #[must_use]
141 pub fn http(host: impl Into<String>, port: u16) -> Self {
142 Self::new(ProxyType::Http, host, port)
143 }
144
145 #[inline]
147 #[must_use]
148 pub fn https(host: impl Into<String>, port: u16) -> Self {
149 Self::new(ProxyType::Https, host, port)
150 }
151
152 #[inline]
154 #[must_use]
155 pub fn socks4(host: impl Into<String>, port: u16) -> Self {
156 Self::new(ProxyType::Socks4, host, port)
157 }
158
159 #[inline]
164 #[must_use]
165 pub fn socks5(host: impl Into<String>, port: u16) -> Self {
166 Self {
167 proxy_type: ProxyType::Socks5,
168 host: host.into(),
169 port,
170 username: None,
171 password: None,
172 proxy_dns: true, }
174 }
175
176 #[inline]
178 #[must_use]
179 pub fn direct() -> Self {
180 Self {
181 proxy_type: ProxyType::Direct,
182 host: String::new(),
183 port: 0,
184 username: None,
185 password: None,
186 proxy_dns: false,
187 }
188 }
189}
190
191impl ProxyConfig {
196 #[must_use]
203 pub fn with_credentials(
204 mut self,
205 username: impl Into<String>,
206 password: impl Into<String>,
207 ) -> Self {
208 self.username = Some(username.into());
209 self.password = Some(password.into());
210 self
211 }
212
213 #[must_use]
217 pub fn with_proxy_dns(mut self, proxy_dns: bool) -> Self {
218 self.proxy_dns = proxy_dns;
219 self
220 }
221}
222
223impl ProxyConfig {
228 #[inline]
230 #[must_use]
231 pub fn has_auth(&self) -> bool {
232 self.username.is_some() && self.password.is_some()
233 }
234
235 #[inline]
237 #[must_use]
238 pub fn is_socks(&self) -> bool {
239 matches!(self.proxy_type, ProxyType::Socks4 | ProxyType::Socks5)
240 }
241
242 #[inline]
244 #[must_use]
245 pub fn is_http(&self) -> bool {
246 matches!(self.proxy_type, ProxyType::Http | ProxyType::Https)
247 }
248}
249
250#[cfg(test)]
255mod tests {
256 use super::{ProxyConfig, ProxyType};
257
258 #[test]
263 fn test_proxy_type_as_str() {
264 assert_eq!(ProxyType::Http.as_str(), "http");
265 assert_eq!(ProxyType::Https.as_str(), "https");
266 assert_eq!(ProxyType::Socks4.as_str(), "socks4");
267 assert_eq!(ProxyType::Socks5.as_str(), "socks");
268 assert_eq!(ProxyType::Direct.as_str(), "direct");
269 }
270
271 #[test]
272 fn test_proxy_type_serialization() {
273 assert_eq!(
274 serde_json::to_string(&ProxyType::Http).unwrap(),
275 r#""http""#
276 );
277 assert_eq!(
278 serde_json::to_string(&ProxyType::Https).unwrap(),
279 r#""https""#
280 );
281 assert_eq!(
282 serde_json::to_string(&ProxyType::Socks4).unwrap(),
283 r#""socks4""#
284 );
285 assert_eq!(
286 serde_json::to_string(&ProxyType::Socks5).unwrap(),
287 r#""socks""#
288 );
289 assert_eq!(
290 serde_json::to_string(&ProxyType::Direct).unwrap(),
291 r#""direct""#
292 );
293 }
294
295 #[test]
296 fn test_proxy_type_default() {
297 assert_eq!(ProxyType::default(), ProxyType::Direct);
298 }
299
300 #[test]
305 fn test_proxy_config_http() {
306 let proxy = ProxyConfig::http("proxy.example.com", 8080);
307 assert_eq!(proxy.proxy_type, ProxyType::Http);
308 assert_eq!(proxy.host, "proxy.example.com");
309 assert_eq!(proxy.port, 8080);
310 assert!(!proxy.has_auth());
311 assert!(proxy.is_http());
312 assert!(!proxy.is_socks());
313 }
314
315 #[test]
316 fn test_proxy_config_https() {
317 let proxy = ProxyConfig::https("proxy.example.com", 8443);
318 assert_eq!(proxy.proxy_type, ProxyType::Https);
319 assert!(proxy.is_http());
320 }
321
322 #[test]
323 fn test_proxy_config_socks4() {
324 let proxy = ProxyConfig::socks4("proxy.example.com", 1080);
325 assert_eq!(proxy.proxy_type, ProxyType::Socks4);
326 assert!(proxy.is_socks());
327 assert!(!proxy.is_http());
328 }
329
330 #[test]
331 fn test_proxy_config_socks5() {
332 let proxy = ProxyConfig::socks5("proxy.example.com", 1080);
333 assert_eq!(proxy.proxy_type, ProxyType::Socks5);
334 assert!(proxy.is_socks());
335 assert!(proxy.proxy_dns); }
337
338 #[test]
339 fn test_proxy_config_direct() {
340 let proxy = ProxyConfig::direct();
341 assert_eq!(proxy.proxy_type, ProxyType::Direct);
342 assert!(!proxy.is_http());
343 assert!(!proxy.is_socks());
344 }
345
346 #[test]
347 fn test_proxy_config_with_auth() {
348 let proxy = ProxyConfig::socks5("proxy.example.com", 1080)
349 .with_credentials("user", "pass")
350 .with_proxy_dns(true);
351
352 assert_eq!(proxy.proxy_type, ProxyType::Socks5);
353 assert!(proxy.has_auth());
354 assert!(proxy.is_socks());
355 assert!(proxy.proxy_dns);
356 assert_eq!(proxy.username.as_deref(), Some("user"));
357 assert_eq!(proxy.password.as_deref(), Some("pass"));
358 }
359
360 #[test]
361 fn test_proxy_config_serialization() {
362 let proxy = ProxyConfig::http("proxy.example.com", 8080).with_credentials("user", "pass");
363
364 let json = serde_json::to_string(&proxy).unwrap();
365 assert!(json.contains(r#""type":"http""#));
366 assert!(json.contains(r#""host":"proxy.example.com""#));
367 assert!(json.contains(r#""port":8080"#));
368 assert!(json.contains(r#""username":"user""#));
369 }
370
371 #[test]
372 fn test_proxy_config_clone() {
373 let proxy = ProxyConfig::http("proxy.example.com", 8080);
374 let cloned = proxy.clone();
375 assert_eq!(proxy.host, cloned.host);
376 assert_eq!(proxy.port, cloned.port);
377 }
378}