1use {axum::{http::StatusCode,
4 response::{IntoResponse,
5 Response}},
6 thiserror::Error};
7
8pub type Result<T> = std::result::Result<T, JetError>;
10
11#[derive(Error, Debug)]
13pub enum JetError {
14 #[error("Failed to decode protobuf: {0}")]
16 ProtobufDecode(#[from] prost::DecodeError),
17
18 #[error("Failed to encode protobuf: {0}")]
20 ProtobufEncode(#[from] prost::EncodeError),
21
22 #[error("Invalid content type: expected {expected}, got {actual}")]
24 InvalidContentType { expected: String, actual: String },
25
26 #[error("Missing Content-Type header")]
28 MissingContentType,
29
30 #[error("Request body too large: {size} bytes (max: {max})")]
32 BodyTooLarge { size: usize, max: usize },
33
34 #[error("HTTP client error: {0}")]
36 HttpClient(#[from] reqwest::Error),
37
38 #[error("JSON error: {0}")]
40 Json(#[from] serde_json::Error),
41
42 #[error("IO error: {0}")]
44 Io(#[from] std::io::Error),
45
46 #[error("Failed to bind server: {0}")]
48 ServerBind(String),
49
50 #[error("Internal server error: {0}")]
52 Internal(String),
53
54 #[error("Bad request: {0}")]
56 BadRequest(String),
57
58 #[error("Not found: {0}")]
60 NotFound(String),
61
62 #[error("Unauthorized: {0}")]
64 Unauthorized(String),
65
66 #[error("Forbidden: {0}")]
68 Forbidden(String),
69}
70
71impl JetError {
72 pub fn status_code(&self) -> StatusCode {
74 match self {
75 | JetError::ProtobufDecode(_) => StatusCode::BAD_REQUEST,
76 | JetError::ProtobufEncode(_) => StatusCode::INTERNAL_SERVER_ERROR,
77 | JetError::InvalidContentType { .. } => StatusCode::UNSUPPORTED_MEDIA_TYPE,
78 | JetError::MissingContentType => StatusCode::BAD_REQUEST,
79 | JetError::BodyTooLarge { .. } => StatusCode::PAYLOAD_TOO_LARGE,
80 | JetError::HttpClient(_) => StatusCode::BAD_GATEWAY,
81 | JetError::Json(_) => StatusCode::BAD_REQUEST,
82 | JetError::Io(_) => StatusCode::INTERNAL_SERVER_ERROR,
83 | JetError::ServerBind(_) => StatusCode::INTERNAL_SERVER_ERROR,
84 | JetError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
85 | JetError::BadRequest(_) => StatusCode::BAD_REQUEST,
86 | JetError::NotFound(_) => StatusCode::NOT_FOUND,
87 | JetError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
88 | JetError::Forbidden(_) => StatusCode::FORBIDDEN,
89 }
90 }
91}
92
93impl IntoResponse for JetError {
94 fn into_response(self) -> Response {
95 let status = self.status_code();
96 let body = self.to_string();
97
98 (status, body).into_response()
99 }
100}