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 = "Forbidden")]
32    Forbidden(String),
33
34    #[display(fmt = "Unauthorized")]
35    Unauthorized(String),
36
37    #[display(fmt = "MethodNotAllowed")]
38    MethodNotAllowed(String),
39
40    // ? -----------------------------------------------------------------------
41    // ? Server errors (5xx)
42    // ? -----------------------------------------------------------------------
43    #[display(fmt = "InternalServerError")]
44    InternalServerError(String),
45}
46
47impl error::ResponseError for GatewayError {
48    fn error_response(&self) -> HttpResponse {
49        HttpResponse::build(self.status_code())
50            .insert_header(ContentType::json())
51            .json(HttpJsonResponse {
52                msg: self.to_string(),
53                status: self.status_code().as_u16(),
54                message: match self {
55                    GatewayError::BadRequest(msg) => msg.to_owned(),
56                    GatewayError::Forbidden(msg) => msg.to_owned(),
57                    GatewayError::Unauthorized(msg) => msg.to_owned(),
58                    GatewayError::MethodNotAllowed(msg) => msg.to_owned(),
59                    GatewayError::InternalServerError(msg) => msg.to_owned(),
60                },
61            })
62    }
63
64    fn status_code(&self) -> StatusCode {
65        match *self {
66            GatewayError::BadRequest { .. } => StatusCode::BAD_REQUEST,
67            GatewayError::Forbidden { .. } => StatusCode::FORBIDDEN,
68            GatewayError::Unauthorized { .. } => StatusCode::UNAUTHORIZED,
69            GatewayError::MethodNotAllowed { .. } => {
70                StatusCode::METHOD_NOT_ALLOWED
71            }
72            GatewayError::InternalServerError { .. } => {
73                StatusCode::INTERNAL_SERVER_ERROR
74            }
75        }
76    }
77}