Skip to main content

rs_zero/rest/
error.rs

1use axum::response::IntoResponse;
2use thiserror::Error;
3
4use crate::rest::response::ApiResponse;
5
6/// Result type used by REST helpers.
7pub type RestResult<T> = Result<T, RestError>;
8
9/// Errors returned by REST middleware and handlers.
10#[derive(Debug, Error)]
11pub enum RestError {
12    #[error("unauthorized")]
13    Unauthorized,
14
15    #[error("request timed out")]
16    Timeout,
17
18    #[error("service unavailable: {0}")]
19    ServiceUnavailable(String),
20
21    #[error("concurrency limit reached")]
22    ConcurrencyLimit,
23
24    #[error("rate limit exceeded")]
25    RateLimited,
26
27    #[error("service overloaded")]
28    Overloaded,
29
30    #[error("bad request: {0}")]
31    BadRequest(String),
32
33    #[error("internal error: {0}")]
34    Internal(String),
35}
36
37impl RestError {
38    /// Stable error code for uniform JSON responses.
39    pub fn code(&self) -> &'static str {
40        match self {
41            Self::Unauthorized => "UNAUTHORIZED",
42            Self::Timeout => "TIMEOUT",
43            Self::ServiceUnavailable(_) => "SERVICE_UNAVAILABLE",
44            Self::ConcurrencyLimit => "CONCURRENCY_LIMIT",
45            Self::RateLimited => "RATE_LIMITED",
46            Self::Overloaded => "OVERLOADED",
47            Self::BadRequest(_) => "BAD_REQUEST",
48            Self::Internal(_) => "INTERNAL",
49        }
50    }
51}
52
53impl IntoResponse for RestError {
54    fn into_response(self) -> axum::response::Response {
55        ApiResponse::<()>::fail(self.code(), self.to_string()).into_response()
56    }
57}