Skip to main content

modo/error/
http_error.rs

1//! [`HttpError`] enum for mapping well-known HTTP error codes to [`Error`].
2
3use http::StatusCode;
4
5use super::Error;
6
7/// A lightweight enum of common HTTP error statuses.
8///
9/// Use this when you want a concise, copy-able representation of an error category without
10/// allocating a message string. It converts into [`Error`] via `From<HttpError>`.
11///
12/// # Example
13///
14/// ```rust
15/// use modo::error::{Error, HttpError};
16///
17/// let err: Error = HttpError::NotFound.into();
18/// assert_eq!(err.message(), "Not Found");
19/// ```
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub enum HttpError {
22    /// 400 Bad Request
23    BadRequest,
24    /// 401 Unauthorized
25    Unauthorized,
26    /// 403 Forbidden
27    Forbidden,
28    /// 404 Not Found
29    NotFound,
30    /// 405 Method Not Allowed
31    MethodNotAllowed,
32    /// 409 Conflict
33    Conflict,
34    /// 410 Gone
35    Gone,
36    /// 422 Unprocessable Entity
37    UnprocessableEntity,
38    /// 429 Too Many Requests
39    TooManyRequests,
40    /// 413 Payload Too Large
41    PayloadTooLarge,
42    /// 500 Internal Server Error
43    InternalServerError,
44    /// 502 Bad Gateway
45    BadGateway,
46    /// 503 Service Unavailable
47    ServiceUnavailable,
48    /// 504 Gateway Timeout
49    GatewayTimeout,
50}
51
52impl HttpError {
53    /// Returns the [`StatusCode`] corresponding to this variant.
54    pub fn status_code(self) -> StatusCode {
55        match self {
56            Self::BadRequest => StatusCode::BAD_REQUEST,
57            Self::Unauthorized => StatusCode::UNAUTHORIZED,
58            Self::Forbidden => StatusCode::FORBIDDEN,
59            Self::NotFound => StatusCode::NOT_FOUND,
60            Self::MethodNotAllowed => StatusCode::METHOD_NOT_ALLOWED,
61            Self::Conflict => StatusCode::CONFLICT,
62            Self::Gone => StatusCode::GONE,
63            Self::UnprocessableEntity => StatusCode::UNPROCESSABLE_ENTITY,
64            Self::TooManyRequests => StatusCode::TOO_MANY_REQUESTS,
65            Self::PayloadTooLarge => StatusCode::PAYLOAD_TOO_LARGE,
66            Self::InternalServerError => StatusCode::INTERNAL_SERVER_ERROR,
67            Self::BadGateway => StatusCode::BAD_GATEWAY,
68            Self::ServiceUnavailable => StatusCode::SERVICE_UNAVAILABLE,
69            Self::GatewayTimeout => StatusCode::GATEWAY_TIMEOUT,
70        }
71    }
72
73    /// Returns the canonical HTTP reason phrase for this variant.
74    pub fn message(self) -> &'static str {
75        match self {
76            Self::BadRequest => "Bad Request",
77            Self::Unauthorized => "Unauthorized",
78            Self::Forbidden => "Forbidden",
79            Self::NotFound => "Not Found",
80            Self::MethodNotAllowed => "Method Not Allowed",
81            Self::Conflict => "Conflict",
82            Self::Gone => "Gone",
83            Self::UnprocessableEntity => "Unprocessable Entity",
84            Self::TooManyRequests => "Too Many Requests",
85            Self::PayloadTooLarge => "Payload Too Large",
86            Self::InternalServerError => "Internal Server Error",
87            Self::BadGateway => "Bad Gateway",
88            Self::ServiceUnavailable => "Service Unavailable",
89            Self::GatewayTimeout => "Gateway Timeout",
90        }
91    }
92}
93
94/// Converts an [`HttpError`] into an [`Error`] using its canonical status code and message.
95impl From<HttpError> for Error {
96    fn from(http_err: HttpError) -> Self {
97        Error::new(http_err.status_code(), http_err.message())
98    }
99}