error.rs
1 use std::process::ExitStatus; 2 3 use axum::http; 4 use axum::response::{IntoResponse, Response}; 5 6 /// Errors relating to the Git backend. 7 #[derive(Debug, thiserror::Error)] 8 pub enum GitError { 9 /// The entity was not found. 10 #[error("not found")] 11 NotFound, 12 13 /// I/O error. 14 #[error("i/o error: {0}")] 15 Io(#[from] std::io::Error), 16 17 /// The service is not available. 18 #[error("service '{0}' not available")] 19 ServiceUnavailable(&'static str), 20 21 /// Invalid identifier. 22 #[error("invalid radicle identifier: {0}")] 23 Id(#[from] radicle::identity::IdError), 24 25 /// Storage error. 26 #[error("storage: {0}")] 27 Storage(#[from] radicle::storage::Error), 28 29 /// Repository error. 30 #[error("repository: {0}")] 31 Repository(#[from] radicle::storage::RepositoryError), 32 33 /// Git backend error. 34 #[error("git-http-backend: exited with code {0}")] 35 BackendExited(ExitStatus), 36 37 /// Git backend error. 38 #[error("git-http-backend: invalid header returned: {0:?}")] 39 BackendHeader(String), 40 41 /// HeaderName error. 42 #[error(transparent)] 43 InvalidHeaderName(#[from] axum::http::header::InvalidHeaderName), 44 45 /// HeaderValue error. 46 #[error(transparent)] 47 InvalidHeaderValue(#[from] axum::http::header::InvalidHeaderValue), 48 } 49 50 impl GitError { 51 pub fn status(&self) -> http::StatusCode { 52 match self { 53 GitError::ServiceUnavailable(_) => http::StatusCode::SERVICE_UNAVAILABLE, 54 GitError::Id(_) => http::StatusCode::NOT_FOUND, 55 GitError::NotFound => http::StatusCode::NOT_FOUND, 56 _ => http::StatusCode::INTERNAL_SERVER_ERROR, 57 } 58 } 59 } 60 61 impl IntoResponse for GitError { 62 fn into_response(self) -> Response { 63 tracing::error!("{}", self); 64 65 self.status().into_response() 66 } 67 } 68 69 /// Errors relating to the `/raw` route. 70 #[derive(Debug, thiserror::Error)] 71 pub enum RawError { 72 /// Surf error. 73 #[error(transparent)] 74 Surf(#[from] radicle_surf::Error), 75 76 /// Payload error. 77 #[error(transparent)] 78 ProjectPayload(#[from] radicle::identity::PayloadError), 79 80 /// Io error. 81 #[error(transparent)] 82 Io(#[from] std::io::Error), 83 84 /// Archive error. 85 #[error("`git archive` exited with status {0}:\n{1}")] 86 Archive(ExitStatus, String), 87 88 /// Git error. 89 #[error(transparent)] 90 Git(#[from] radicle::git::raw::Error), 91 92 /// Radicle Storage error. 93 #[error(transparent)] 94 Storage(#[from] radicle::storage::Error), 95 96 /// Repository error. 97 #[error(transparent)] 98 Repository(#[from] radicle::storage::RepositoryError), 99 100 /// Http Headers error. 101 #[error(transparent)] 102 Headers(#[from] http::header::InvalidHeaderValue), 103 104 /// Surf file error. 105 #[error(transparent)] 106 SurfFile(#[from] radicle_surf::fs::error::File), 107 108 /// The entity was not found. 109 #[error("not found")] 110 NotFound, 111 } 112 113 impl RawError { 114 pub fn status(&self) -> http::StatusCode { 115 match self { 116 RawError::SurfFile(_) | RawError::NotFound => http::StatusCode::NOT_FOUND, 117 _ => http::StatusCode::INTERNAL_SERVER_ERROR, 118 } 119 } 120 } 121 122 impl IntoResponse for RawError { 123 fn into_response(self) -> Response { 124 tracing::error!("{}", self); 125 126 self.status().into_response() 127 } 128 }