Skip to main content

a3s_boot/
error.rs

1use thiserror::Error;
2
3/// Errors returned while building or serving a Boot application.
4#[derive(Debug, Error)]
5pub enum BootError {
6    #[error("module name cannot be empty")]
7    EmptyModuleName,
8    #[error("route path must start with '/': {0}")]
9    InvalidRoutePath(String),
10    #[error("route is already registered: {0}")]
11    DuplicateRoute(String),
12    #[error("route was not found: {0}")]
13    NotFound(String),
14    #[error("method is not allowed: {0}")]
15    MethodNotAllowed(String),
16    #[error("provider token is already registered: {0}")]
17    DuplicateProvider(String),
18    #[error("provider token is not registered: {0}")]
19    MissingProvider(String),
20    #[error("provider token has a different concrete type: {0}")]
21    ProviderTypeMismatch(String),
22    #[error("request was forbidden: {0}")]
23    Forbidden(String),
24    #[error("request was unauthorized: {0}")]
25    Unauthorized(String),
26    #[error("bad request: {0}")]
27    BadRequest(String),
28    #[error("payload is too large: {0}")]
29    PayloadTooLarge(String),
30    #[error("unsupported media type: {0}")]
31    UnsupportedMediaType(String),
32    #[error("not acceptable: {0}")]
33    NotAcceptable(String),
34    #[error("adapter error: {0}")]
35    Adapter(String),
36    #[error("internal error: {0}")]
37    Internal(String),
38    #[error("I/O error: {0}")]
39    Io(#[from] std::io::Error),
40}
41
42impl BootError {
43    /// HTTP status code that adapters should use for this error.
44    pub fn http_status_code(&self) -> u16 {
45        match self {
46            Self::NotFound(_) => 404,
47            Self::MethodNotAllowed(_) => 405,
48            Self::Unauthorized(_) => 401,
49            Self::Forbidden(_) => 403,
50            Self::BadRequest(_) => 400,
51            Self::PayloadTooLarge(_) => 413,
52            Self::UnsupportedMediaType(_) => 415,
53            Self::NotAcceptable(_) => 406,
54            _ => 500,
55        }
56    }
57
58    /// Text response body that adapters should use for this error.
59    pub fn http_response_message(&self) -> String {
60        match self {
61            Self::NotFound(message)
62            | Self::MethodNotAllowed(message)
63            | Self::Unauthorized(message)
64            | Self::Forbidden(message)
65            | Self::BadRequest(message)
66            | Self::PayloadTooLarge(message)
67            | Self::UnsupportedMediaType(message)
68            | Self::NotAcceptable(message) => message.clone(),
69            error => error.to_string(),
70        }
71    }
72
73    pub(crate) fn clone_for_filter(&self) -> Self {
74        match self {
75            Self::EmptyModuleName => Self::EmptyModuleName,
76            Self::InvalidRoutePath(message) => Self::InvalidRoutePath(message.clone()),
77            Self::DuplicateRoute(message) => Self::DuplicateRoute(message.clone()),
78            Self::NotFound(message) => Self::NotFound(message.clone()),
79            Self::MethodNotAllowed(message) => Self::MethodNotAllowed(message.clone()),
80            Self::DuplicateProvider(message) => Self::DuplicateProvider(message.clone()),
81            Self::MissingProvider(message) => Self::MissingProvider(message.clone()),
82            Self::ProviderTypeMismatch(message) => Self::ProviderTypeMismatch(message.clone()),
83            Self::Forbidden(message) => Self::Forbidden(message.clone()),
84            Self::Unauthorized(message) => Self::Unauthorized(message.clone()),
85            Self::BadRequest(message) => Self::BadRequest(message.clone()),
86            Self::PayloadTooLarge(message) => Self::PayloadTooLarge(message.clone()),
87            Self::UnsupportedMediaType(message) => Self::UnsupportedMediaType(message.clone()),
88            Self::NotAcceptable(message) => Self::NotAcceptable(message.clone()),
89            Self::Adapter(message) => Self::Adapter(message.clone()),
90            Self::Internal(message) => Self::Internal(message.clone()),
91            Self::Io(error) => Self::Io(std::io::Error::new(error.kind(), error.to_string())),
92        }
93    }
94}