gooty_proxy/definitions/errors.rs
1//! # Error Types
2//!
3//! This module provides a comprehensive set of error types used throughout the gooty-proxy crate.
4//! Each error type is designed to encapsulate specific failure modes for different subsystems.
5//!
6//! ## Overview
7//!
8//! The module contains several error enums, each focused on a specific domain:
9//!
10//! - `CidrError`: For errors related to CIDR notation and subnet operations
11//! - `RequestorError`: For HTTP request related failures
12//! - `FilestoreError`: For disk operations and file management errors
13//! - `ConfigError`: For configuration parsing and validation errors
14//! - `ProxyError`: For proxy-specific validation and connection errors
15//! - `SourceError`: For proxy source acquisition failures
16//! - `JudgementError`: For proxy validation and testing errors
17//! - `UtilError`: For general utility function failures
18//! - `OwnershipError`: For ASN and organization lookup failures
19//! - `SleuthError`: For IP investigation failures
20//! - `ManagerError`: For high-level proxy management errors
21//!
22//! Each error type has a corresponding `Result` type alias for more convenient function signatures.
23//!
24//! ## Examples
25//!
26//! ```
27//! use gooty_proxy::definitions::errors::{CidrError, CidrResult};
28//!
29//! fn parse_cidr(input: &str) -> CidrResult<()> {
30//! if !input.contains('/') {
31//! return Err(CidrError::InvalidFormat("Missing prefix".to_string()));
32//! }
33//! // Additional parsing logic...
34//! Ok(())
35//! }
36//! ```
37
38use reqwest::StatusCode;
39use std::path::PathBuf;
40use thiserror::Error;
41
42/// Represents error types that can occur during CIDR operations.
43///
44/// This enum provides detailed error variants for invalid CIDR formats,
45/// IP address issues, and prefix length validation.
46///
47/// # Examples
48///
49/// ```
50/// use gooty_proxy::definitions::errors::CidrError;
51///
52/// let error = CidrError::InvalidFormat("Invalid CIDR".to_string());
53/// println!("Error: {}", error);
54/// ```
55#[derive(Debug, Error)]
56pub enum CidrError {
57 /// Indicates that the provided CIDR string does not follow the correct format.
58 ///
59 /// The format should be `IP_ADDRESS/PREFIX_LENGTH`, such as "192.168.1.0/24".
60 #[error("Invalid CIDR format: {0}")]
61 InvalidFormat(String),
62
63 /// Indicates that the IP address portion of a CIDR string is not valid.
64 ///
65 /// The IP address should be a valid IPv4 or IPv6 address.
66 #[error("Invalid IP address: {0}")]
67 InvalidIpAddress(String),
68
69 /// Indicates that the prefix length portion of a CIDR string is not valid.
70 ///
71 /// For IPv4, the prefix length should be between 0 and 32.
72 /// For IPv6, the prefix length should be between 0 and 128.
73 #[error("Invalid prefix length: {0}")]
74 InvalidPrefixLength(String),
75
76 /// Indicates that there's a mismatch between the IP version and the context.
77 ///
78 /// This typically occurs when trying to use an IPv4 address in an IPv6 context or vice versa.
79 #[error("IP version mismatch")]
80 IpVersionMismatch,
81}
82
83/// Result type for CIDR operations
84pub type CidrResult<T> = Result<T, CidrError>;
85
86/// Error types that can occur during HTTP requests
87#[derive(Debug, Error)]
88pub enum RequestorError {
89 /// Encapsulates an underlying reqwest library error.
90 ///
91 /// This typically occurs for network-level issues such as DNS failures,
92 /// connection problems, or TLS errors.
93 #[error("HTTP request error: {0}")]
94 RequestError(#[from] reqwest::Error),
95
96 /// Indicates that a request did not complete within the specified timeout period.
97 ///
98 /// The associated value represents the number of seconds the system waited before timing out.
99 #[error("Request timed out after {0} seconds")]
100 Timeout(u64),
101
102 /// Indicates that the server responded with a non-success status code.
103 ///
104 /// Includes both the status code and any error message from the response body.
105 #[error("Server returned status code {0}: {1}")]
106 StatusError(StatusCode, String),
107
108 /// Represents errors specific to proxy connection failures.
109 ///
110 /// This could include authentication failures, connection refused errors,
111 /// or other proxy-specific connectivity issues.
112 #[error("Proxy connection error: {0}")]
113 ProxyError(String),
114}
115
116/// Result type for HTTP requests
117pub type RequestResult<T> = Result<T, RequestorError>;
118
119/// Errors that can occur in the filestore
120#[derive(Debug, Error)]
121pub enum FilestoreError {
122 /// Represents general I/O errors that occur during file operations.
123 ///
124 /// This includes file not found errors, permission issues, etc.
125 #[error("I/O error: {0}")]
126 IoError(String),
127
128 /// Represents errors that occur when serializing data to TOML format.
129 ///
130 /// This typically happens when data structures contain types that cannot be serialized to TOML.
131 #[error("TOML serialization error: {0}")]
132 TomlSerError(#[from] toml::ser::Error),
133
134 /// Represents errors that occur when deserializing data from TOML format.
135 ///
136 /// This can happen when the TOML content doesn't match the expected structure.
137 #[error("TOML deserialization error: {0}")]
138 TomlDeError(#[from] toml::de::Error),
139
140 /// Represents errors that occur when serializing or deserializing JSON data.
141 ///
142 /// This typically occurs when JSON data doesn't match the expected structure
143 /// or when data structures cannot be serialized to valid JSON.
144 #[error("JSON serialization error: {0}")]
145 JsonSerError(#[from] serde_json::Error),
146
147 /// Indicates that a provided file or directory path is invalid.
148 ///
149 /// This could be due to path components containing invalid characters,
150 /// or paths that are too long for the operating system.
151 #[error("Invalid path: {0}")]
152 InvalidPath(String),
153
154 /// Indicates that creating a directory failed.
155 ///
156 /// This could be due to permissions, the parent directory not existing,
157 /// or the path already exists as a file.
158 #[error("Directory creation failed: {0}")]
159 DirectoryCreationFailed(String),
160
161 /// Indicates that a requested file could not be found.
162 ///
163 /// This typically occurs when trying to read from a non-existent file.
164 #[error("File not found: {0}")]
165 FileNotFound(String),
166
167 /// Represents errors that occur when parsing file contents.
168 ///
169 /// This could include syntax errors in configuration files or
170 /// invalid data formats.
171 #[error("Parse error: {0}")]
172 ParseError(String),
173
174 /// Represents errors that occur when serializing data to any format.
175 ///
176 /// This is a general error for serialization issues that aren't specific
177 /// to a particular format like TOML or JSON.
178 #[error("Serialization error: {0}")]
179 SerializationError(String),
180}
181
182/// Result type for filestore operations
183pub type FilestoreResult<T> = Result<T, FilestoreError>;
184
185/// Errors that can occur during configuration operations
186#[derive(Debug, Error)]
187pub enum ConfigError {
188 /// Encapsulates an underlying I/O error from the standard library.
189 ///
190 /// This typically occurs when reading from or writing to configuration files.
191 #[error("I/O error: {0}")]
192 IoError(#[from] std::io::Error),
193
194 /// Represents errors that occur when serializing data to TOML format.
195 ///
196 /// This typically happens when configuration data contains types
197 /// that cannot be serialized to TOML.
198 #[error("TOML serialization error: {0}")]
199 TomlSerError(#[from] toml::ser::Error),
200
201 /// Represents errors that occur when deserializing data from TOML format.
202 ///
203 /// This can happen when the TOML configuration content doesn't match
204 /// the expected structure.
205 #[error("TOML deserialization error: {0}")]
206 TomlDeError(#[from] toml::de::Error),
207
208 /// Indicates that a required configuration file was not found.
209 ///
210 /// The associated `PathBuf` indicates which file was missing.
211 #[error("Missing required configuration file: {0}")]
212 MissingConfig(PathBuf),
213
214 /// Indicates that a configuration value is invalid or out of acceptable range.
215 ///
216 /// This could include type mismatches, values out of range, or invalid formats.
217 #[error("Invalid configuration value: {0}")]
218 InvalidValue(String),
219
220 /// Indicates that a required section in a configuration file is missing.
221 ///
222 /// Configuration files are often organized into sections, and this error
223 /// indicates that a required section was not found.
224 #[error("Missing required configuration section: {0}")]
225 MissingSection(String),
226
227 /// Indicates that the configuration doesn't match the expected schema.
228 ///
229 /// This could include missing fields, incorrect data types, or
230 /// constraint violations.
231 #[error("Configuration schema error: {0}")]
232 SchemaError(String),
233
234 /// Indicates that a configuration directory was not found.
235 ///
236 /// This typically occurs when trying to load multiple configuration
237 /// files from a directory that doesn't exist.
238 #[error("Configuration directory not found: {0}")]
239 DirectoryNotFound(PathBuf),
240}
241
242/// Result type for configuration operations
243pub type ConfigResult<T> = Result<T, ConfigError>;
244
245/// Errors that can occur when validating or working with proxies
246#[derive(Debug, Error)]
247pub enum ProxyError {
248 /// Indicates that a port number is invalid.
249 ///
250 /// Port numbers must be between 0 and 65535, with some ports requiring
251 /// special permissions.
252 #[error("Invalid port number: {0}")]
253 InvalidPort(u16),
254
255 /// Indicates that authentication is required but was not provided.
256 ///
257 /// Some proxy types require username/password authentication.
258 #[error("Missing required authentication for proxy type")]
259 MissingAuthentication,
260
261 /// Indicates that the proxy configuration is invalid.
262 ///
263 /// This could include invalid protocols, malformed URLs, or
264 /// incompatible options.
265 #[error("Invalid proxy configuration: {0}")]
266 InvalidConfiguration(String),
267
268 /// Represents errors that occur when connecting to a proxy.
269 ///
270 /// This includes connection refused, authentication failures,
271 /// or timeouts when trying to establish a connection.
272 #[error("Connection error: {0}")]
273 ConnectionError(String),
274}
275
276/// Represents an error that can occur when working with proxy sources
277#[derive(Debug, Error)]
278pub enum SourceError {
279 /// Indicates that a URL is invalid or malformed.
280 ///
281 /// This typically occurs when a proxy source URL doesn't follow RFC 3986.
282 #[error("Invalid URL: {0}")]
283 InvalidUrl(String),
284
285 /// Indicates that a regular expression pattern is invalid.
286 ///
287 /// This can occur when extracting proxy information using regex patterns.
288 #[error("Invalid regex pattern: {0}")]
289 InvalidRegexPattern(String),
290
291 /// Indicates that fetching proxies from a source failed.
292 ///
293 /// This could be due to network issues, rate limiting, or the source being offline.
294 #[error("Failed to fetch from source: {0}")]
295 FetchFailure(String),
296
297 /// Indicates that the response from a source couldn't be parsed.
298 ///
299 /// This typically occurs when a source returns data in an unexpected format.
300 #[error("Failed to parse source response: {0}")]
301 ParseError(String),
302}
303
304/// Result type for source operations
305pub type SourceResult<T> = Result<T, SourceError>;
306
307/// Error types that can occur during proxy judgement
308#[derive(Debug, Error)]
309pub enum JudgementError {
310 /// Encapsulates an underlying requestor error.
311 ///
312 /// This occurs when HTTP requests made during proxy testing fail.
313 #[error("Request error: {0}")]
314 RequestError(#[from] RequestorError),
315
316 /// Indicates that no judge URL was configured for testing proxies.
317 ///
318 /// A judge URL is required to verify that proxies are working correctly.
319 #[error("Judge URL not configured")]
320 NoJudgeUrl,
321
322 /// Indicates that the response from a judge couldn't be parsed.
323 ///
324 /// This typically occurs when a judge returns data in an unexpected format.
325 #[error("Failed to parse judge response: {0}")]
326 ParseError(String),
327
328 /// Indicates that a proxy check operation timed out.
329 ///
330 /// This occurs when a proxy takes too long to respond during testing.
331 #[error("Proxy check timed out")]
332 Timeout,
333
334 /// Indicates that a proxy check failed.
335 ///
336 /// This could be due to the proxy being offline, returning incorrect data,
337 /// or otherwise not behaving as expected.
338 #[error("Proxy check failed: {0}")]
339 ProxyFailure(String),
340
341 /// Represents miscellaneous errors that don't fit other categories.
342 ///
343 /// This is a catch-all for errors that aren't covered by more specific variants.
344 #[error("{0}")]
345 Other(String),
346}
347
348/// Result type for judgement operations
349pub type JudgementResult<T> = Result<T, JudgementError>;
350
351/// Error types for utility functions
352#[derive(Debug, Error)]
353pub enum UtilError {
354 /// Indicates that a URL is invalid or malformed.
355 ///
356 /// This typically occurs when a URL doesn't follow RFC 3986.
357 #[error("Invalid URL: {0}")]
358 InvalidUrl(String),
359
360 /// Indicates that an IP address is invalid or malformed.
361 ///
362 /// This can occur when an address doesn't follow IPv4 or IPv6 format.
363 #[error("Invalid IP address: {0}")]
364 InvalidIpAddress(String),
365
366 /// Indicates that a port number is invalid.
367 ///
368 /// Port numbers must be between 0 and 65535.
369 #[error("Invalid port number: {0}")]
370 InvalidPort(u16),
371
372 /// Indicates that a regular expression pattern is invalid.
373 ///
374 /// This can occur when constructing regex patterns for various parsing operations.
375 #[error("Invalid regex pattern: {0}")]
376 InvalidRegex(String),
377}
378
379/// Result type for utility functions
380pub type UtilResult<T> = Result<T, UtilError>;
381
382/// Error types that can occur during ASN and organization lookups
383#[derive(Debug, Error)]
384pub enum OwnershipError {
385 /// Represents network-related errors during ownership lookups.
386 ///
387 /// This includes connection failures, DNS issues, or timeouts.
388 #[error("Network error: {0}")]
389 NetworkError(String),
390
391 /// Indicates that the response from an ownership lookup couldn't be parsed.
392 ///
393 /// This typically occurs when an API returns data in an unexpected format.
394 #[error("Parse error: {0}")]
395 ParseError(String),
396
397 /// Represents errors returned by external APIs during ownership lookups.
398 ///
399 /// This could include authentication failures or invalid request errors.
400 #[error("API error: {0}")]
401 ApiError(String),
402
403 /// Indicates that requested ownership information was not found.
404 ///
405 /// This can occur when looking up ASN/organization information for an IP
406 /// that isn't allocated or isn't in the database.
407 #[error("Resource not found: {0}")]
408 NotFound(String),
409
410 /// Indicates that requests are being rate-limited by an external API.
411 ///
412 /// This typically requires waiting before making additional requests.
413 #[error("Rate limited")]
414 RateLimited,
415}
416
417/// Result type for ownership operations
418pub type OwnershipResult<T> = Result<T, OwnershipError>;
419
420/// Errors that can occur during IP lookup operations
421#[derive(Debug, Error)]
422pub enum SleuthError {
423 /// Represents network-related errors during IP lookups.
424 ///
425 /// This includes connection failures, DNS issues, or timeouts.
426 #[error("Network error: {0}")]
427 NetworkError(String),
428
429 /// Indicates that the response from an IP lookup couldn't be parsed.
430 ///
431 /// This typically occurs when an API returns data in an unexpected format.
432 #[error("Parse error: {0}")]
433 ParseError(String),
434
435 /// Represents errors returned by external APIs during IP lookups.
436 ///
437 /// This could include authentication failures or invalid request errors.
438 #[error("API error: {0}")]
439 ApiError(String),
440
441 /// Indicates that requested IP information was not found.
442 ///
443 /// This can occur when looking up information for an IP that isn't
444 /// allocated or isn't in the database.
445 #[error("Resource not found: {0}")]
446 NotFound(String),
447
448 /// Indicates that requests are being rate-limited by an external API.
449 ///
450 /// This typically requires waiting before making additional requests.
451 #[error("Rate limited")]
452 RateLimited,
453
454 /// Encapsulates an underlying ownership lookup error.
455 ///
456 /// This occurs when ownership lookup operations fail during IP investigation.
457 #[error("Ownership lookup error: {0}")]
458 OwnershipError(#[from] OwnershipError),
459}
460
461/// Result type for Sleuth operations
462pub type SleuthResult<T> = Result<T, SleuthError>;
463
464/// Errors that can occur in the proxy manager
465#[derive(Debug, Error)]
466pub enum ManagerError {
467 /// Encapsulates an underlying proxy validation error.
468 ///
469 /// This occurs when proxy objects fail validation checks.
470 #[error("Proxy validation error: {0}")]
471 ProxyError(#[from] ProxyError),
472
473 /// Encapsulates an underlying source error.
474 ///
475 /// This occurs when operations related to proxy sources fail.
476 #[error("Source error: {0}")]
477 SourceError(#[from] SourceError),
478
479 /// Encapsulates an underlying judgment error.
480 ///
481 /// This occurs when proxy testing and validation operations fail.
482 #[error("Judgment error: {0}")]
483 JudgementError(#[from] JudgementError),
484
485 /// Encapsulates an underlying requestor error.
486 ///
487 /// This occurs when HTTP requests made during proxy management fail.
488 #[error("Requestor error: {0}")]
489 RequestorError(#[from] RequestorError),
490
491 /// Encapsulates an underlying sleuth error.
492 ///
493 /// This occurs when IP investigation operations fail.
494 #[error("Sleuth error: {0}")]
495 SleuthError(#[from] SleuthError),
496
497 /// Indicates that a proxy ID is invalid or not found in the system.
498 ///
499 /// This typically occurs when operations reference proxies that don't exist.
500 #[error("Invalid proxy ID: {0}")]
501 InvalidProxyId(String),
502
503 /// Indicates that a source ID is invalid or not found in the system.
504 ///
505 /// This typically occurs when operations reference sources that don't exist.
506 #[error("Invalid source ID: {0}")]
507 InvalidSourceId(String),
508}
509
510/// Result type for proxy manager operations
511pub type ManagerResult<T> = Result<T, ManagerError>;