105 lines
2.8 KiB
Rust
Raw Normal View History

use std::fmt;
2025-10-07 10:59:52 +01:00
use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
/// Registry error types
#[derive(Debug, thiserror::Error)]
pub enum RegistryError {
#[error("Extension not found: {0}")]
NotFound(String),
#[error("Invalid extension type: {0}")]
InvalidType(String),
#[error("Invalid version format: {0}")]
InvalidVersion(String),
#[error("Gitea API error: {0}")]
Gitea(String),
#[error("Forgejo API error: {0}")]
Forgejo(String),
#[error("GitHub API error: {0}")]
Github(String),
2025-10-07 10:59:52 +01:00
#[error("OCI registry error: {0}")]
Oci(String),
#[error("Cache error: {0}")]
Cache(String),
#[error("HTTP request error: {0}")]
Http(#[from] reqwest::Error),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("JSON serialization error: {0}")]
Json(#[from] serde_json::Error),
#[error("Configuration error: {0}")]
Config(String),
#[error("Authentication error: {0}")]
Auth(String),
#[error("Rate limit exceeded")]
RateLimit,
#[error("No backends configured")]
NoBackendsConfigured,
#[error("All backends failed: {0}")]
MultiBackendFailure(String),
2025-10-07 10:59:52 +01:00
#[error("Internal server error: {0}")]
Internal(String),
}
/// Result type alias
pub type Result<T> = std::result::Result<T, RegistryError>;
/// API error response
#[derive(Debug, serde::Serialize)]
pub struct ApiErrorResponse {
pub error: String,
pub message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub details: Option<String>,
}
impl IntoResponse for RegistryError {
fn into_response(self) -> Response {
let (status, error_type) = match &self {
RegistryError::NotFound(_) => (StatusCode::NOT_FOUND, "not_found"),
RegistryError::InvalidType(_) => (StatusCode::BAD_REQUEST, "invalid_type"),
RegistryError::InvalidVersion(_) => (StatusCode::BAD_REQUEST, "invalid_version"),
RegistryError::Auth(_) => (StatusCode::UNAUTHORIZED, "auth_error"),
RegistryError::RateLimit => (StatusCode::TOO_MANY_REQUESTS, "rate_limit"),
RegistryError::Config(_) | RegistryError::NoBackendsConfigured => {
(StatusCode::INTERNAL_SERVER_ERROR, "config_error")
}
RegistryError::MultiBackendFailure(_) => {
(StatusCode::SERVICE_UNAVAILABLE, "backend_failure")
}
2025-10-07 10:59:52 +01:00
_ => (StatusCode::INTERNAL_SERVER_ERROR, "internal_error"),
};
let body = ApiErrorResponse {
error: error_type.to_string(),
message: self.to_string(),
details: None,
};
(status, axum::Json(body)).into_response()
}
}
impl fmt::Display for ApiErrorResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}: {}", self.error, self.message)
}
}