1use axum::{http::StatusCode, response::{IntoResponse, Response}, Json};
2use serde_json::json;
3use thiserror::Error;
4
5#[derive(Error, Debug)]
6pub enum RegistryError {
7 #[error("unauthorized")]
8 Unauthorized,
9
10 #[error("layer not found: {0}")]
11 NotFound(String),
12
13 #[error("version already exists: {0}")]
14 Conflict(String),
15
16 #[error("bad request: {0}")]
17 BadRequest(String),
18
19 #[error("database error: {0}")]
20 Database(#[from] rusqlite::Error),
21
22 #[error("storage error: {0}")]
23 Storage(String),
24
25 #[error("internal error: {0}")]
26 Internal(String),
27}
28
29impl IntoResponse for RegistryError {
30 fn into_response(self) -> Response {
31 let (status, message) = match &self {
32 RegistryError::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()),
33 RegistryError::NotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
34 RegistryError::Conflict(_) => (StatusCode::CONFLICT, self.to_string()),
35 RegistryError::BadRequest(_) => (StatusCode::BAD_REQUEST, self.to_string()),
36 RegistryError::Database(e) => {
37 tracing::error!("database error: {}", e);
38 (StatusCode::INTERNAL_SERVER_ERROR, "internal error".to_string())
39 }
40 RegistryError::Storage(msg) => {
41 tracing::error!("storage error: {}", msg);
42 (StatusCode::INTERNAL_SERVER_ERROR, "storage error".to_string())
43 }
44 RegistryError::Internal(msg) => {
45 tracing::error!("internal error: {}", msg);
46 (StatusCode::INTERNAL_SERVER_ERROR, "internal error".to_string())
47 }
48 };
49 (status, Json(json!({"error": message}))).into_response()
50 }
51}
52
53pub type Result<T> = std::result::Result<T, RegistryError>;