simbld_http/responses/
mod.rs1#[macro_use]
12pub mod actix_responder;
13pub mod client;
14pub mod crawler;
15pub mod informational;
16pub mod local;
17pub mod redirection;
18pub mod server;
19pub mod service;
20pub mod success;
21
22use crate::helpers::response_helpers;
24use crate::traits::get_description_trait::GetDescription;
25pub use actix_responder::CustomResponse;
26pub use client::ResponsesClientCodes;
27pub use crawler::ResponsesCrawlerCodes;
28pub use informational::ResponsesInformationalCodes;
29pub use local::ResponsesLocalApiCodes;
30pub use redirection::ResponsesRedirectionCodes;
31pub use server::ResponsesServerCodes;
32pub use service::ResponsesServiceCodes;
33pub use success::ResponsesSuccessCodes;
34
35use crate::helpers::http_code_helper::HttpCode;
37
38#[derive(Debug, Clone, Copy, PartialEq)]
41pub enum ResponsesTypes {
42 Informational(ResponsesInformationalCodes),
44 Success(ResponsesSuccessCodes),
45 Redirection(ResponsesRedirectionCodes),
46 ClientError(ResponsesClientCodes),
47 ServerError(ResponsesServerCodes),
48 ServiceError(ResponsesServiceCodes),
49 CrawlerError(ResponsesCrawlerCodes),
50 LocalApiError(ResponsesLocalApiCodes),
51}
52
53impl ResponsesTypes {
54 pub fn get_code(&self) -> u16 {
56 match self {
57 ResponsesTypes::Informational(code) => code.get_code(),
58 ResponsesTypes::Success(code) => code.get_code(),
59 ResponsesTypes::Redirection(code) => code.get_code(),
60 ResponsesTypes::ClientError(code) => code.get_code(),
61 ResponsesTypes::ServerError(code) => code.get_code(),
62 ResponsesTypes::ServiceError(code) => code.get_code(),
63 ResponsesTypes::CrawlerError(code) => code.get_code(),
64 ResponsesTypes::LocalApiError(code) => code.get_code(),
65 }
66 }
67
68 pub fn as_json(&self) -> serde_json::Value {
70 match self {
71 ResponsesTypes::Informational(code) => code.as_json(),
72 ResponsesTypes::Success(code) => code.as_json(),
73 ResponsesTypes::Redirection(code) => code.as_json(),
74 ResponsesTypes::ClientError(code) => code.as_json(),
75 ResponsesTypes::ServerError(code) => code.as_json(),
76 ResponsesTypes::ServiceError(code) => code.as_json(),
77 ResponsesTypes::CrawlerError(code) => code.as_json(),
78 ResponsesTypes::LocalApiError(code) => code.as_json(),
79 }
80 }
81
82 pub fn as_tuple(&self) -> HttpCode {
84 match self {
85 ResponsesTypes::Informational(code) => code.to_http_code(),
86 ResponsesTypes::Success(code) => code.to_http_code(),
87 ResponsesTypes::Redirection(code) => code.to_http_code(),
88 ResponsesTypes::ClientError(code) => code.to_http_code(),
89 ResponsesTypes::ServerError(code) => code.to_http_code(),
90 ResponsesTypes::ServiceError(code) => code.to_http_code(),
91 ResponsesTypes::CrawlerError(code) => code.to_http_code(),
92 ResponsesTypes::LocalApiError(code) => code.to_http_code(),
93 }
94 }
95
96 pub fn from_u16(code: u16) -> Option<Self> {
98 if let Some(c) = ResponsesInformationalCodes::from_u16(code) {
99 return Some(ResponsesTypes::Informational(c));
100 }
101 if let Some(c) = ResponsesSuccessCodes::from_u16(code) {
102 return Some(ResponsesTypes::Success(c));
103 }
104 if let Some(c) = ResponsesRedirectionCodes::from_u16(code) {
105 return Some(ResponsesTypes::Redirection(c));
106 }
107 if let Some(c) = ResponsesClientCodes::from_u16(code) {
108 return Some(ResponsesTypes::ClientError(c));
109 }
110 if let Some(c) = ResponsesServerCodes::from_u16(code) {
111 return Some(ResponsesTypes::ServerError(c));
112 }
113 if let Some(c) = ResponsesServiceCodes::from_u16(code) {
114 return Some(ResponsesTypes::ServiceError(c));
115 }
116 if let Some(c) = ResponsesCrawlerCodes::from_u16(code) {
117 return Some(ResponsesTypes::CrawlerError(c));
118 }
119 if let Some(c) = ResponsesLocalApiCodes::from_u16(code) {
120 return Some(ResponsesTypes::LocalApiError(c));
121 }
122 None
123 }
124
125 pub fn get_description(&self) -> &'static str {
127 match self {
128 ResponsesTypes::Informational(code_enum) => {
129 code_enum.get_description_field("Description").unwrap_or("No description")
130 }
131 ResponsesTypes::Success(code_enum) => {
132 code_enum.get_description_field("Description").unwrap_or("No description")
133 }
134 ResponsesTypes::Redirection(code_enum) => {
135 code_enum.get_description_field("Description").unwrap_or("No description")
136 }
137 ResponsesTypes::ClientError(code_enum) => {
138 code_enum.get_description_field("Description").unwrap_or("No description")
139 }
140 ResponsesTypes::ServerError(code_enum) => {
141 code_enum.get_description_field("Description").unwrap_or("No description")
142 }
143 ResponsesTypes::ServiceError(code_enum) => {
144 code_enum.get_description_field("Description").unwrap_or("No description")
145 }
146 ResponsesTypes::CrawlerError(code_enum) => {
147 code_enum.get_description_field("Description").unwrap_or("No description")
148 }
149 ResponsesTypes::LocalApiError(code_enum) => {
150 code_enum.get_description_field("Description").unwrap_or("No description")
151 }
152 }
153 }
154
155 pub fn get_response_get_description(&self) -> (u16, &'static str) {
157 match self {
158 ResponsesTypes::Informational(code) => {
159 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
160 }
161 ResponsesTypes::Success(code) => {
162 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
163 }
164 ResponsesTypes::Redirection(code) => {
165 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
166 }
167 ResponsesTypes::ClientError(code) => {
168 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
169 }
170 ResponsesTypes::ServerError(code) => {
171 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
172 }
173 ResponsesTypes::ServiceError(code) => {
174 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
175 }
176 ResponsesTypes::CrawlerError(code) => {
177 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
178 }
179 ResponsesTypes::LocalApiError(code) => {
180 (code.get_code(), code.get_description_field("Description").unwrap_or(""))
181 }
182 }
183 }
184
185 pub fn as_normalized_json(&self) -> serde_json::Value {
187 if let Some(normalized) = response_helpers::get_response_by_type(self) {
188 normalized.as_json()
189 } else {
190 self.as_json()
191 }
192 }
193
194 pub fn to_tuple(&self) -> (u16, &'static str, &'static str) {
196 let http_code = self.as_tuple();
197 (http_code.standard_code, http_code.standard_name, http_code.unified_description)
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use serde_json::json;
205
206 #[test]
207 fn test_get_code() {
208 assert_eq!(
209 ResponsesTypes::CrawlerError(ResponsesCrawlerCodes::ParsingErrorUnfinishedHeader)
210 .get_code(),
211 400
212 );
213 }
214
215 #[test]
216 fn test_as_identical_tuple() {
217 let tuple_result = ResponsesTypes::Success(ResponsesSuccessCodes::Ok).as_tuple();
219 assert_eq!(tuple_result.standard_code, 200);
220 assert_eq!(tuple_result.standard_name, "OK");
221 assert_eq!(tuple_result.unified_description, "Request processed successfully. Response will depend on the request method used, and the result will be either a representation of the requested resource or an empty response");
222 assert_eq!(tuple_result.internal_code, None);
223 assert_eq!(tuple_result.internal_name, None);
224 }
225
226 #[test]
227 fn test_as_different_tuple() {
228 let tuple_result_diff =
230 ResponsesTypes::ServerError(ResponsesServerCodes::OriginIsUnreachable).as_tuple();
231 assert_eq!(tuple_result_diff.standard_code, 502);
232 assert_eq!(tuple_result_diff.standard_name, "Bad Gateway");
233 assert_eq!(tuple_result_diff.unified_description, "The origin server could not be contacted. This might be due to network issues or misconfiguration");
234 assert_eq!(tuple_result_diff.internal_code, Some(523));
235 assert_eq!(tuple_result_diff.internal_name, Some("Origin Is Unreachable"));
236 }
237
238 #[test]
239 fn test_as_json() {
240 let json_value =
241 ResponsesTypes::ServerError(ResponsesServerCodes::OriginIsUnreachable).as_json();
242 let expected_json = json!({
243 "type": "Server errors",
244 "details": {
245 "standard http code": {
246 "code": 502,
247 "name": "Bad Gateway"
248 },
249 "description": "The origin server could not be contacted. This might be due to network issues or misconfiguration",
250 "internal http code": {
251 "code": 523,
252 "name": "Origin Is Unreachable"
253 }
254 }
255 });
256 assert_eq!(json_value, expected_json);
257 }
258
259 #[test]
260 fn test_from_u16() {
261 assert_eq!(
262 ResponsesTypes::from_u16(700),
263 Some(ResponsesTypes::CrawlerError(ResponsesCrawlerCodes::ParsingErrorUnfinishedHeader))
264 );
265 assert_eq!(ResponsesTypes::from_u16(999), None);
266 }
267
268 #[test]
269 fn test_as_normalized() {
270 let client_error = ResponsesTypes::ClientError(ResponsesClientCodes::BadRequest);
271
272 let normalized = response_helpers::get_response_by_type(&client_error);
274
275 assert_eq!(normalized, Some(ResponsesTypes::ClientError(ResponsesClientCodes::BadRequest)));
277
278 let unknown_code = ResponsesTypes::from_u16(9999);
280 let normalized_unknown =
281 unknown_code.as_ref().and_then(|code| response_helpers::get_response_by_type(code));
282
283 assert_eq!(normalized_unknown, None);
284 }
285
286 #[test]
287 fn test_get_advance_response_get_description() {
288 let client_error = ResponsesTypes::ClientError(ResponsesClientCodes::SSLCertificateError);
289 let (code, description) =
290 response_helpers::get_advance_response_get_description(client_error);
291
292 assert_eq!(code, 400);
293 assert_eq!(description, "An invalid or untrusted SSL certificate was encountered");
294 }
295}