use thiserror::Error;
#[derive(Debug, Error)]
pub enum RdapError {
#[error("Invalid input: {0}")]
InvalidInput(String),
#[error("SSRF protection blocked request to {url}: {reason}")]
SsrfBlocked { url: String, reason: String },
#[error("Only HTTPS is allowed, got: {scheme}")]
InsecureScheme { scheme: String },
#[error("No RDAP server found for: {query}")]
NoServerFound { query: String },
#[error("Bootstrap fetch failed for {resource}: {source}")]
BootstrapFetch {
resource: String,
#[source]
source: Box<RdapError>,
},
#[error("Network error: {0}")]
Network(#[from] reqwest::Error),
#[error("RDAP server returned HTTP {status} for {url}")]
HttpStatus { status: u16, url: String },
#[error("Request timed out after {millis}ms: {url}")]
Timeout { millis: u64, url: String },
#[error("Failed to parse RDAP response: {reason}")]
ParseError { reason: String },
#[error("RDAP response missing objectClassName")]
MissingObjectClass,
#[error("Unknown RDAP objectClassName: {class}")]
UnknownObjectClass { class: String },
#[error("Cache error: {0}")]
Cache(String),
#[error("Invalid URL '{url}': {source}")]
InvalidUrl {
url: String,
#[source]
source: url::ParseError,
},
}
impl RdapError {
pub fn status_code(&self) -> u16 {
match self {
RdapError::InvalidInput(_) => 400,
RdapError::SsrfBlocked { .. } => 403,
RdapError::InsecureScheme { .. } => 403,
RdapError::NoServerFound { .. } => 404,
RdapError::HttpStatus { status, .. } => *status,
RdapError::Timeout { .. } => 408,
RdapError::Network(_) => 502,
RdapError::BootstrapFetch { .. } => 502,
RdapError::ParseError { .. } => 500,
RdapError::MissingObjectClass => 500,
RdapError::UnknownObjectClass { .. } => 500,
RdapError::Cache(_) => 500,
RdapError::InvalidUrl { .. } => 400,
}
}
pub fn is_invalid_input(&self) -> bool {
matches!(self, RdapError::InvalidInput(_))
}
pub fn is_network(&self) -> bool {
matches!(
self,
RdapError::Network(_) | RdapError::Timeout { .. } | RdapError::HttpStatus { .. }
)
}
pub fn is_ssrf_blocked(&self) -> bool {
matches!(
self,
RdapError::SsrfBlocked { .. } | RdapError::InsecureScheme { .. }
)
}
}
pub type Result<T> = std::result::Result<T, RdapError>;