Skip to main content

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>;