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 /// Git2 error. 77 #[error(transparent)] 78 Git2(#[from] radicle::git::raw::Error), 79 80 /// Payload error. 81 #[error(transparent)] 82 ProjectPayload(#[from] radicle::identity::PayloadError), 83 84 /// Io error. 85 #[error(transparent)] 86 Io(#[from] std::io::Error), 87 88 /// Archive error. 89 #[error("`git archive` exited with status {0}:\n{1}")] 90 Archive(ExitStatus, String), 91 92 /// Git error. 93 #[error(transparent)] 94 Git(#[from] radicle::git::ext::Error), 95 96 /// Radicle Storage error. 97 #[error(transparent)] 98 Storage(#[from] radicle::storage::Error), 99 100 /// Repository error. 101 #[error(transparent)] 102 Repository(#[from] radicle::storage::RepositoryError), 103 104 /// Http Headers error. 105 #[error(transparent)] 106 Headers(#[from] http::header::InvalidHeaderValue), 107 108 /// Surf file error. 109 #[error(transparent)] 110 SurfFile(#[from] radicle_surf::fs::error::File), 111 112 /// The entity was not found. 113 #[error("not found")] 114 NotFound, 115 } 116 117 impl RawError { 118 pub fn status(&self) -> http::StatusCode { 119 match self { 120 RawError::SurfFile(_) | RawError::NotFound => http::StatusCode::NOT_FOUND, 121 _ => http::StatusCode::INTERNAL_SERVER_ERROR, 122 } 123 } 124 } 125 126 impl IntoResponse for RawError { 127 fn into_response(self) -> Response { 128 tracing::error!("{}", self); 129 130 self.status().into_response() 131 } 132 }