myc_http_tools/utils/
json_response.rs

1use actix_web::HttpResponse;
2use serde::Serialize;
3use std::fmt::{Display, Formatter, Result as FmtResult};
4use utoipa::{ToResponse, ToSchema};
5
6#[derive(Debug, Serialize, ToResponse, ToSchema)]
7#[serde(rename_all = "camelCase")]
8pub struct HttpJsonResponse {
9    #[serde(skip_serializing_if = "Option::is_none")]
10    msg: Option<String>,
11
12    #[serde(skip_serializing_if = "Option::is_none")]
13    code: Option<String>,
14
15    #[serde(skip_serializing_if = "Option::is_none")]
16    body: Option<String>,
17}
18
19impl HttpJsonResponse {
20    pub fn new_message<T: ToString>(msg: T) -> Self {
21        Self {
22            msg: msg.to_string().into(),
23            code: None,
24            body: None,
25        }
26    }
27
28    pub fn new_body<T: Serialize>(body: T) -> Result<Self, HttpResponse> {
29        match serde_json::to_string(&body) {
30            Err(err) => {
31                let json_error = HttpJsonResponse::new_message(err.to_string());
32
33                return Err(
34                    HttpResponse::InternalServerError().json(json_error)
35                );
36            }
37            Ok(body) => Ok(Self {
38                msg: None,
39                code: None,
40                body: Some(body),
41            }),
42        }
43    }
44
45    pub fn new_vec_body<T: Serialize>(
46        body: Vec<T>,
47    ) -> Result<Self, HttpResponse> {
48        match serde_json::to_string(&body) {
49            Err(err) => {
50                let json_error = HttpJsonResponse::new_message(err.to_string());
51
52                return Err(
53                    HttpResponse::InternalServerError().json(json_error)
54                );
55            }
56            Ok(body) => Ok(Self {
57                msg: None,
58                code: None,
59                body: Some(body),
60            }),
61        }
62    }
63
64    pub fn with_code<T: ToString>(&self, code: T) -> Self {
65        Self {
66            msg: self.msg.to_owned(),
67            code: Some(code.to_string()),
68            body: self.body.to_owned(),
69        }
70    }
71
72    pub fn with_code_str(&self, code: &'static str) -> Self {
73        Self {
74            msg: self.msg.to_owned(),
75            code: Some(code.to_string()),
76            body: self.body.to_owned(),
77        }
78    }
79
80    pub fn with_body(&self, body: String) -> Self {
81        Self {
82            msg: self.msg.to_owned(),
83            code: self.code.to_owned(),
84            body: Some(body),
85        }
86    }
87
88    pub fn with_serializable_body<T: Serialize>(
89        &self,
90        body: T,
91    ) -> Result<Self, HttpResponse> {
92        match serde_json::to_string(&body) {
93            Err(err) => {
94                let json_error = HttpJsonResponse::new_message(err.to_string());
95
96                return Err(
97                    HttpResponse::InternalServerError().json(json_error)
98                );
99            }
100            Ok(body) => Ok(Self {
101                msg: self.msg.to_owned(),
102                code: self.code.to_owned(),
103                body: Some(body),
104            }),
105        }
106    }
107}
108
109impl Display for HttpJsonResponse {
110    fn fmt(&self, f: &mut Formatter) -> FmtResult {
111        let msg = self.msg.to_owned().unwrap_or("no message".to_string());
112
113        if self.code.is_some() {
114            return write!(f, "{}: {}", self.code.as_ref().unwrap(), msg);
115        }
116
117        write!(f, "{}", msg)
118    }
119}
120
121// * ---------------------------------------------------------------------------
122// * TESTS
123// * ---------------------------------------------------------------------------
124
125#[cfg(test)]
126mod tests {
127
128    use super::*;
129
130    #[test]
131    fn test_json_error() {
132        let json_error = HttpJsonResponse::new_message("test".to_string());
133        assert_eq!(json_error.msg, Some("test".to_string()));
134        assert_eq!(json_error.code, None);
135    }
136
137    #[test]
138    fn test_json_error_code() {
139        let json_error = HttpJsonResponse::new_message("test".to_string())
140            .with_code_str("code");
141        assert_eq!(json_error.msg, Some("test".to_string()));
142        assert_eq!(json_error.code, Some("code".to_string()));
143    }
144
145    #[test]
146    fn test_json_error_display() {
147        let json_error = HttpJsonResponse::new_message("test".to_string());
148        assert_eq!(format!("{}", json_error), "test");
149
150        let json_error = HttpJsonResponse::new_message("test".to_string())
151            .with_code_str("code");
152        assert_eq!(format!("{}", json_error), "code: test");
153    }
154}