at_jet/
error.rs

1//! Error types for AT-Jet
2
3use {axum::{http::StatusCode,
4            response::{IntoResponse,
5                       Response}},
6     thiserror::Error};
7
8/// Result type alias for AT-Jet operations
9pub type Result<T> = std::result::Result<T, JetError>;
10
11/// Error types for AT-Jet
12#[derive(Error, Debug)]
13pub enum JetError {
14  /// Failed to decode protobuf message
15  #[error("Failed to decode protobuf: {0}")]
16  ProtobufDecode(#[from] prost::DecodeError),
17
18  /// Failed to encode protobuf message
19  #[error("Failed to encode protobuf: {0}")]
20  ProtobufEncode(#[from] prost::EncodeError),
21
22  /// Invalid content type
23  #[error("Invalid content type: expected {expected}, got {actual}")]
24  InvalidContentType { expected: String, actual: String },
25
26  /// Missing content type header
27  #[error("Missing Content-Type header")]
28  MissingContentType,
29
30  /// Request body too large
31  #[error("Request body too large: {size} bytes (max: {max})")]
32  BodyTooLarge { size: usize, max: usize },
33
34  /// HTTP client error
35  #[error("HTTP client error: {0}")]
36  HttpClient(#[from] reqwest::Error),
37
38  /// JSON serialization/deserialization error
39  #[error("JSON error: {0}")]
40  Json(#[from] serde_json::Error),
41
42  /// IO error
43  #[error("IO error: {0}")]
44  Io(#[from] std::io::Error),
45
46  /// Server bind error
47  #[error("Failed to bind server: {0}")]
48  ServerBind(String),
49
50  /// Internal server error
51  #[error("Internal server error: {0}")]
52  Internal(String),
53
54  /// Bad request
55  #[error("Bad request: {0}")]
56  BadRequest(String),
57
58  /// Not found
59  #[error("Not found: {0}")]
60  NotFound(String),
61
62  /// Unauthorized
63  #[error("Unauthorized: {0}")]
64  Unauthorized(String),
65
66  /// Forbidden
67  #[error("Forbidden: {0}")]
68  Forbidden(String),
69}
70
71impl JetError {
72  /// Get HTTP status code for this error
73  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}