myc_http_tools/
responses.rs

1use actix_web::{
2    error,
3    http::{header::ContentType, StatusCode},
4    HttpResponse,
5};
6use derive_more::Display;
7use serde::Serialize;
8use std::fmt::Debug;
9
10/// The default JSON response from API errors
11///
12/// Use it in replacement of the simple html body.
13#[derive(Debug, Serialize)]
14pub(crate) struct HttpJsonResponse {
15    msg: String,
16    status: u16,
17    message: String,
18}
19
20/// Internal errors as HTTP responses
21///
22/// Forwarding errors are fired only by Stomata errors.
23#[derive(Debug, Display)]
24pub enum GatewayError {
25    // ? -----------------------------------------------------------------------
26    // ? Client errors (4xx)
27    // ? -----------------------------------------------------------------------
28    #[display(fmt = "BadRequest")]
29    BadRequest(String),
30
31    #[display(fmt = "BadGateway")]
32    BadGateway(String),
33
34    #[display(fmt = "Forbidden")]
35    Forbidden(String),
36
37    #[display(fmt = "Unauthorized")]
38    Unauthorized(String),
39
40    #[display(fmt = "MethodNotAllowed")]
41    MethodNotAllowed(String),
42
43    // ? -----------------------------------------------------------------------
44    // ? Server errors (5xx)
45    // ? -----------------------------------------------------------------------
46    #[display(fmt = "InternalServerError")]
47    InternalServerError(String),
48}
49
50impl error::ResponseError for GatewayError {
51    fn error_response(&self) -> HttpResponse {
52        HttpResponse::build(self.status_code())
53            .insert_header(ContentType::json())
54            .json(HttpJsonResponse {
55                msg: self.to_string(),
56                status: self.status_code().as_u16(),
57                message: match self {
58                    GatewayError::BadRequest(msg) => msg.to_owned(),
59                    GatewayError::BadGateway(msg) => msg.to_owned(),
60                    GatewayError::Forbidden(msg) => msg.to_owned(),
61                    GatewayError::Unauthorized(msg) => msg.to_owned(),
62                    GatewayError::MethodNotAllowed(msg) => msg.to_owned(),
63                    GatewayError::InternalServerError(msg) => msg.to_owned(),
64                },
65            })
66    }
67
68    fn status_code(&self) -> StatusCode {
69        match *self {
70            GatewayError::BadRequest { .. } => StatusCode::BAD_REQUEST,
71            GatewayError::BadGateway { .. } => StatusCode::BAD_GATEWAY,
72            GatewayError::Forbidden { .. } => StatusCode::FORBIDDEN,
73            GatewayError::Unauthorized { .. } => StatusCode::UNAUTHORIZED,
74            GatewayError::MethodNotAllowed { .. } => {
75                StatusCode::METHOD_NOT_ALLOWED
76            }
77            GatewayError::InternalServerError { .. } => {
78                StatusCode::INTERNAL_SERVER_ERROR
79            }
80        }
81    }
82}