1use crate::contracts::ResponseCodeContract;
2use crate::enums::ResponseCode;
3#[cfg(feature = "reqwest")]
4use crate::helpers::reqwest::ReqwestResponseError;
5use crate::helpers::responder::Responder;
6use log::error;
7#[cfg(feature = "multipart")]
8use medullah_multipart::{ErrorMessage as MultipartErrorMessage, MultipartError};
9use ntex::http::error::BlockingError;
10use ntex::http::StatusCode;
11use ntex::web::{HttpRequest, WebResponseError};
12use std::fmt::{Debug, Display, Formatter};
13use std::io;
14use std::ops::Deref;
15
16pub enum AppMessage {
17 UnAuthorized,
18 Forbidden,
19 InternalServerError,
20 InternalServerErrorMessage(&'static str),
21 Anyhow(anyhow::Error),
22 IoError(io::Error),
23 UuidError(uuid::Error),
24 Redirect(&'static str),
25 SuccessMessage(&'static str),
26 SuccessMessageString(String),
27 WarningMessage(&'static str),
28 WarningMessageString(String),
29 HttpClientError(String, String),
30 #[cfg(feature = "hmac")]
31 HmacError(hmac::digest::InvalidLength),
32 UnAuthorizedMessage(&'static str),
33 UnAuthorizedMessageString(String),
34 ForbiddenMessage(&'static str),
35 ForbiddenMessageString(String),
36 #[cfg(feature = "validator")]
37 FormValidationError(validator::ValidationErrors),
38 EntityNotFound(String),
39 #[cfg(feature = "reqwest")]
40 ReqwestError(reqwest::Error),
41 #[cfg(feature = "reqwest")]
42 ReqwestResponseError(ReqwestResponseError),
43 #[cfg(feature = "mailer")]
44 MailerError(reqwest::Error),
45 #[cfg(feature = "multipart")]
46 MultipartError(medullah_multipart::MultipartError),
47 #[cfg(feature = "strum")]
48 StrumParseError(strum::ParseError),
49 SerdeError(serde_json::Error),
50 SerdeError500(serde_json::Error),
51 #[cfg(feature = "base64")]
52 Base64Error(base64::DecodeError),
53 JoinError(tokio::task::JoinError),
54 #[cfg(feature = "jwt")]
55 JwtError(jsonwebtoken::errors::Error),
56 #[cfg(feature = "crypto")]
57 ArgonError(argon2::Error),
58 StrUtf8Error(std::str::Utf8Error),
59 FromUtf8Error(std::string::FromUtf8Error),
60 ChronoParseError(chrono::ParseError),
61 #[cfg(feature = "rabbitmq")]
62 RabbitmqError(lapin::Error),
63 #[cfg(feature = "redis")]
64 RedisError(redis::RedisError),
65 #[cfg(feature = "redis")]
66 RedisPoolError(deadpool::managed::PoolError<redis::RedisError>),
67 #[cfg(feature = "rabbitmq")]
68 RmqPoolError(deadpool::managed::PoolError<lapin::Error>),
69 ErrorMessage(String, StatusCode),
70 PayloadError(ntex::http::error::PayloadError),
71 BlockingNtexErrorInnerBoxed(BlockingError<Box<Self>>),
72 BlockingNtexErrorOuterBoxed(Box<BlockingError<Self>>),
73 BlockingNtexIoError(BlockingError<io::Error>),
74 BlockingErrorCanceled,
75 #[cfg(feature = "database")]
76 R2d2Error(r2d2::Error),
77 #[cfg(feature = "database")]
78 DatabaseError(diesel::result::Error),
79}
80
81fn format_message(status: &AppMessage, f: &mut Formatter<'_>) -> std::fmt::Result {
82 f.write_str(get_message(status).as_str())
83}
84
85fn get_message(status: &AppMessage) -> String {
86 match status {
87 AppMessage::Anyhow(err) => err.to_string(),
88 AppMessage::UuidError(err) => err.to_string(),
89 AppMessage::UnAuthorized => {
90 String::from("You are not authorized to access requested resource(s)")
91 }
92 AppMessage::Forbidden => {
93 String::from("You don't have sufficient permissions to access requested resource(s)")
94 }
95 AppMessage::Redirect(url) => format!("Redirecting to '{}'...", url),
96 AppMessage::EntityNotFound(entity) => format!("Such {} does not exits", entity),
97 #[cfg(feature = "database")]
98 AppMessage::R2d2Error(error) => error.to_string(),
99 #[cfg(feature = "rabbitmq")]
100 AppMessage::RmqPoolError(error) => error.to_string(),
101 #[cfg(feature = "jwt")]
102 AppMessage::JwtError(err) => err.to_string(),
103 #[cfg(feature = "crypto")]
104 AppMessage::ArgonError(err) => err.to_string(),
105 #[cfg(feature = "multipart")]
106 AppMessage::MultipartError(err) => err.to_string(),
107 AppMessage::IoError(error) => error.to_string(),
108 AppMessage::SerdeError(error) => error.to_string(),
109 AppMessage::SerdeError500(error) => error.to_string(),
110 #[cfg(feature = "rabbitmq")]
111 AppMessage::RabbitmqError(error) => error.to_string(),
112 #[cfg(feature = "redis")]
113 AppMessage::RedisError(error) => error.to_string(),
114 #[cfg(feature = "redis")]
115 AppMessage::RedisPoolError(error) => error.to_string(),
116 AppMessage::JoinError(error) => error.to_string(),
117 #[cfg(feature = "reqwest")]
118 AppMessage::ReqwestError(error) => error.to_string(),
119 #[cfg(feature = "reqwest")]
120 AppMessage::ReqwestResponseError(error) => error.body().to_owned(),
121 #[cfg(feature = "mailer")]
122 AppMessage::MailerError(error) => error.to_string(),
123 #[cfg(feature = "base64")]
124 AppMessage::Base64Error(error) => error.to_string(),
125 AppMessage::StrUtf8Error(error) => error.to_string(),
126 AppMessage::FromUtf8Error(error) => error.to_string(),
127 AppMessage::ChronoParseError(error) => error.to_string(),
128 AppMessage::BlockingNtexErrorInnerBoxed(error) => error.to_string(),
129 AppMessage::BlockingNtexErrorOuterBoxed(error) => error.to_string(),
130 AppMessage::BlockingNtexIoError(error) => error.to_string(),
131 AppMessage::PayloadError(error) => error.to_string(),
132 AppMessage::WarningMessage(message)
133 | AppMessage::SuccessMessage(message)
134 | AppMessage::ForbiddenMessage(message)
135 | AppMessage::UnAuthorizedMessage(message)
136 | AppMessage::InternalServerErrorMessage(message) => message.to_string(),
137 AppMessage::WarningMessageString(message)
138 | AppMessage::SuccessMessageString(message)
139 | AppMessage::UnAuthorizedMessageString(message)
140 | AppMessage::ForbiddenMessageString(message)
141 | AppMessage::HttpClientError(message, _)
142 | AppMessage::ErrorMessage(message, _) => message.to_string(),
143 #[cfg(feature = "database")]
144 AppMessage::DatabaseError(err) => match err {
145 diesel::result::Error::NotFound => String::from("Such entity not found"),
146 diesel::result::Error::DatabaseError(err, info) => match err {
147 diesel::result::DatabaseErrorKind::UniqueViolation => {
148 error!(
149 "conflict error({:?}): {} [::] {:?}",
150 err,
151 info.message(),
152 info.details()
153 );
154
155 "conflicted with existing entity".to_string()
156 }
157 _ => {
158 error!(
159 "database kind-level-error({:?}): {} [::] {:?}",
160 err,
161 info.message(),
162 info.details()
163 );
164 "something went wrong".to_string()
165 }
166 },
167 _ => {
168 error!("database error: {:?}", err);
169 String::from("Something went wrong")
170 }
171 },
172 #[cfg(feature = "hmac")]
173 AppMessage::HmacError(message) => message.to_string(),
174 #[cfg(feature = "strum")]
175 AppMessage::StrumParseError(message) => message.to_string(),
176 #[cfg(feature = "validator")]
177 AppMessage::FormValidationError(e) => String::from(e.to_string().as_str()),
178 _ => String::from("Internal Server Error"),
179 }
180}
181
182pub fn get_middleware_level_message(app: &AppMessage) -> String {
183 match app {
184 AppMessage::WarningMessage(message) => message.to_string(),
185 AppMessage::WarningMessageString(message) => message.to_owned(),
186 AppMessage::SuccessMessage(message) => message.to_string(),
187 AppMessage::SuccessMessageString(message) => message.to_owned(),
188 AppMessage::UnAuthorizedMessage(message) => message.to_string(),
189 AppMessage::UnAuthorizedMessageString(message) => message.to_owned(),
190 AppMessage::ForbiddenMessage(message) => message.to_string(),
191 AppMessage::ForbiddenMessageString(message) => message.to_owned(),
192 AppMessage::InternalServerErrorMessage(message) => message.to_string(),
193 AppMessage::Anyhow(message) => message.to_string(),
194 #[cfg(feature = "jwt")]
195 AppMessage::JwtError(_) => "failed to authenticate your jwt token".to_string(),
196 _ => {
197 error!("[middleware-level-error] {:?}", app);
198 String::from("Something isn't right, our engineers are on it")
199 }
200 }
201}
202
203fn send_response(message: &AppMessage) -> ntex::web::HttpResponse {
204 match message {
205 AppMessage::EntityNotFound(entity) => Responder::entity_not_found_message(entity),
206 AppMessage::Redirect(url) => ntex::web::HttpResponse::Found()
207 .header(
208 ntex::http::header::HeaderName::from_static("Location"),
209 ntex::http::header::HeaderValue::from_static(url),
210 )
211 .finish()
212 .into_body(),
213 AppMessage::Anyhow(err) => {
214 log::error!("Anyhow Error: {}", err);
215 Responder::internal_server_error()
216 }
217 AppMessage::IoError(message) => {
218 log::error!("IO Error: {}", message);
219 Responder::internal_server_error()
220 }
221 #[cfg(feature = "database")]
222 AppMessage::R2d2Error(message) => {
223 log::error!("R2d2 Error: {}", message);
224 Responder::internal_server_error()
225 }
226 #[cfg(feature = "jwt")]
227 AppMessage::JwtError(message) => {
228 log::error!("Jwt Error: {}", message);
229 Responder::message("invalid jwt token", ResponseCode::Unauthorized)
230 }
231 #[cfg(feature = "crypto")]
232 AppMessage::ArgonError(message) => {
233 log::error!("Argon Error: {}", message);
234 Responder::internal_server_error()
235 }
236 #[cfg(feature = "rabbitmq")]
237 AppMessage::RabbitmqError(message) => {
238 log::error!("Rabbitmq Error: {}", message);
239 Responder::internal_server_error()
240 }
241 #[cfg(feature = "redis")]
242 AppMessage::RedisError(message) => {
243 log::error!("Redis Error: {}", message);
244 Responder::internal_server_error()
245 }
246 #[cfg(feature = "redis")]
247 AppMessage::RedisPoolError(message) => {
248 log::error!("Redis Pool Error: {}", message);
249 Responder::internal_server_error()
250 }
251 #[cfg(feature = "rabbitmq")]
252 AppMessage::RmqPoolError(message) => {
253 log::error!("RabbitMQ Pool Error: {}", message);
254 Responder::internal_server_error()
255 }
256 #[cfg(feature = "reqwest")]
257 AppMessage::ReqwestError(message) => {
258 log::error!("Http Client(Reqwest) Error: {}", message);
259 Responder::internal_server_error()
260 }
261 #[cfg(feature = "reqwest")]
262 AppMessage::ReqwestResponseError(err) => {
263 log::error!("Http Client(Reqwest) Error[{}]: {}", err.code(), err.body());
264 Responder::internal_server_error()
265 }
266 AppMessage::StrUtf8Error(message) => {
267 log::error!("Str-Utf8 Conversion Error: {:?}", message);
268 Responder::internal_server_error()
269 }
270 AppMessage::FromUtf8Error(message) => {
271 log::error!("Utf8 Conversion Error: {:?}", message);
272 Responder::internal_server_error()
273 }
274 #[cfg(feature = "base64")]
275 AppMessage::Base64Error(message) => {
276 log::error!("Base64 Error: {:?}", message);
277 Responder::internal_server_error()
278 }
279 #[cfg(feature = "strum")]
280 AppMessage::StrumParseError(message) => {
281 log::error!("Strum Parse Error: {:?}", message);
282 Responder::internal_server_error()
283 }
284 AppMessage::SerdeError(message) => {
285 log::error!("Serde Error: {:?}", message);
286 Responder::message(&message.to_string(), ResponseCode::BadRequest)
287 }
288 AppMessage::SerdeError500(message) => {
289 log::error!("Serde Error: {}", message);
290 Responder::internal_server_error()
291 }
292 AppMessage::BlockingNtexErrorInnerBoxed(message) => {
293 log::error!("Blocking Error: {}", message);
294 match message {
295 BlockingError::Error(error) => send_response(error),
296 BlockingError::Canceled => Responder::internal_server_error(),
297 }
298 }
299 AppMessage::BlockingNtexErrorOuterBoxed(message) => {
300 log::error!("Blocking Error: {}", message);
301 match message.deref() {
302 BlockingError::Error(error) => send_response(error),
303 BlockingError::Canceled => Responder::internal_server_error(),
304 }
305 }
306 AppMessage::BlockingNtexIoError(message) => {
307 log::error!("Blocking IO Error: {}", message);
308 Responder::internal_server_error()
309 }
310 AppMessage::PayloadError(message) => {
311 log::error!("Payload Extraction Error: {}", message);
312 Responder::internal_server_error()
313 }
314 AppMessage::InternalServerErrorMessage(message) => {
315 log::error!("Internal Server Error: {}", message);
316 Responder::internal_server_error()
317 }
318 AppMessage::SuccessMessage(message) => Responder::ok_message(message),
319 AppMessage::SuccessMessageString(message) => Responder::ok_message(message),
320 AppMessage::ErrorMessage(message, status) => {
321 Responder::message(message, ResponseCode::from_status(*status))
322 }
323 AppMessage::UnAuthorized => {
324 Responder::message(&message.message(), ResponseCode::Unauthorized)
325 }
326 AppMessage::UnAuthorizedMessage(message) => {
327 Responder::message(message, ResponseCode::Unauthorized)
328 }
329 AppMessage::UnAuthorizedMessageString(message) => {
330 Responder::message(message, ResponseCode::Unauthorized)
331 }
332 AppMessage::Forbidden => Responder::message(&message.message(), ResponseCode::Forbidden),
333 AppMessage::ForbiddenMessage(message) => {
334 Responder::message(message, ResponseCode::Forbidden)
335 }
336 AppMessage::ForbiddenMessageString(message) => {
337 Responder::message(message, ResponseCode::Forbidden)
338 }
339 AppMessage::ChronoParseError(error) => {
340 let message = error.to_string();
341 log::error!("Failed To Parse DateTime: {}", message);
342 Responder::message(&message, ResponseCode::BadRequest)
343 }
344 #[cfg(feature = "validator")]
345 AppMessage::FormValidationError(e) => {
346 Responder::send_msg(e, ResponseCode::BadRequest, "Validation Error")
347 }
348 #[cfg(feature = "multipart")]
349 AppMessage::MultipartError(e) => {
350 Responder::send_msg(e.to_string(), ResponseCode::BadRequest, "File Upload Error")
351 }
352 #[cfg(feature = "database")]
353 AppMessage::DatabaseError(err) => match err {
354 diesel::result::Error::NotFound => {
355 Responder::not_found_message("Such entity not found")
356 }
357 diesel::result::Error::DatabaseError(err, _) => {
358 error!("database error: {:?}", err);
359 match err {
360 diesel::result::DatabaseErrorKind::UniqueViolation => {
361 Responder::message(&message.message(), ResponseCode::BadRequest)
362 }
363 _ => Responder::internal_server_error(),
364 }
365 }
366 _ => {
367 error!("database error: {:?}", err);
368 Responder::internal_server_error_message(&message.message())
369 }
370 },
371 #[cfg(feature = "hmac")]
372 AppMessage::HmacError(err) => {
373 error!("{:?}", err);
374 Responder::internal_server_error()
375 }
376 _ => Responder::bad_req_message(get_message(message).as_str()),
377 }
378}
379
380fn get_status_code(status: &AppMessage) -> StatusCode {
381 #[cfg(feature = "database")]
382 use diesel::result::Error as DieselError;
383
384 match status {
385 AppMessage::SuccessMessage(_) | AppMessage::SuccessMessageString(_) => StatusCode::OK,
386 AppMessage::UuidError(_)
387 | AppMessage::WarningMessage(_)
388 | AppMessage::WarningMessageString(_)
389 | AppMessage::SerdeError(_)
390 | AppMessage::ChronoParseError(_) => StatusCode::BAD_REQUEST,
391 AppMessage::EntityNotFound(_msg) => StatusCode::NOT_FOUND,
392 #[cfg(feature = "multipart")]
393 AppMessage::MultipartError(err) => match err {
394 MultipartError::ValidationError(err) => match err.error {
395 MultipartErrorMessage::InvalidFileExtension(_)
396 | MultipartErrorMessage::InvalidContentType(_) => {
397 StatusCode::UNSUPPORTED_MEDIA_TYPE
398 }
399 _ => StatusCode::BAD_REQUEST,
400 },
401 _ => StatusCode::BAD_REQUEST,
402 },
403 #[cfg(feature = "database")]
404 AppMessage::DatabaseError(DieselError::NotFound) => StatusCode::NOT_FOUND,
405 #[cfg(feature = "database")]
406 AppMessage::DatabaseError(DieselError::DatabaseError(
407 diesel::result::DatabaseErrorKind::UniqueViolation,
408 _,
409 )) => StatusCode::CONFLICT,
410 #[cfg(feature = "jwt")]
411 AppMessage::JwtError(_) => StatusCode::UNAUTHORIZED,
412 #[cfg(feature = "validator")]
413 AppMessage::FormValidationError(_) => StatusCode::BAD_REQUEST,
414 AppMessage::ErrorMessage(_, status) => *status,
415 AppMessage::UnAuthorized
416 | AppMessage::UnAuthorizedMessage(_)
417 | AppMessage::UnAuthorizedMessageString(_) => StatusCode::UNAUTHORIZED,
418 AppMessage::Forbidden
419 | AppMessage::ForbiddenMessage(_)
420 | AppMessage::ForbiddenMessageString(_) => StatusCode::FORBIDDEN,
421 _ => StatusCode::INTERNAL_SERVER_ERROR, }
423}
424
425impl Debug for AppMessage {
426 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
427 format_message(self, f)
428 }
429}
430
431#[cfg(feature = "validator")]
432impl From<validator::ValidationErrors> for AppMessage {
433 fn from(value: validator::ValidationErrors) -> Self {
434 AppMessage::FormValidationError(value)
435 }
436}
437
438impl Display for AppMessage {
439 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
440 format_message(self, f)
441 }
442}
443
444impl From<anyhow::Error> for AppMessage {
445 fn from(value: anyhow::Error) -> Self {
446 AppMessage::Anyhow(value)
447 }
448}
449
450impl From<io::Error> for AppMessage {
451 fn from(value: io::Error) -> Self {
452 AppMessage::IoError(value)
453 }
454}
455
456#[cfg(feature = "jwt")]
457impl From<jsonwebtoken::errors::Error> for AppMessage {
458 fn from(value: jsonwebtoken::errors::Error) -> Self {
459 AppMessage::JwtError(value)
460 }
461}
462
463#[cfg(feature = "crypto")]
464impl From<argon2::Error> for AppMessage {
465 fn from(value: argon2::Error) -> Self {
466 AppMessage::ArgonError(value)
467 }
468}
469
470#[cfg(feature = "reqwest")]
471impl From<reqwest::Error> for AppMessage {
472 fn from(value: reqwest::Error) -> Self {
473 AppMessage::ReqwestError(value)
474 }
475}
476
477impl From<ntex::http::error::PayloadError> for AppMessage {
478 fn from(value: ntex::http::error::PayloadError) -> Self {
479 AppMessage::PayloadError(value)
480 }
481}
482
483#[cfg(feature = "database")]
484impl From<r2d2::Error> for AppMessage {
485 fn from(value: r2d2::Error) -> Self {
486 AppMessage::R2d2Error(value)
487 }
488}
489
490impl From<uuid::Error> for AppMessage {
491 fn from(value: uuid::Error) -> Self {
492 AppMessage::UuidError(value)
493 }
494}
495
496impl From<tokio::task::JoinError> for AppMessage {
497 fn from(value: tokio::task::JoinError) -> Self {
498 AppMessage::JoinError(value)
499 }
500}
501
502impl From<BlockingError<AppMessage>> for AppMessage {
503 fn from(value: BlockingError<AppMessage>) -> Self {
504 AppMessage::BlockingNtexErrorOuterBoxed(Box::new(value))
505 }
506}
507
508impl From<BlockingError<Box<AppMessage>>> for AppMessage {
509 fn from(value: BlockingError<Box<AppMessage>>) -> Self {
510 AppMessage::BlockingNtexErrorInnerBoxed(value)
511 }
512}
513
514impl From<BlockingError<io::Error>> for AppMessage {
515 fn from(value: BlockingError<io::Error>) -> Self {
516 AppMessage::BlockingNtexIoError(value)
517 }
518}
519
520#[cfg(feature = "rabbitmq")]
521impl From<lapin::Error> for AppMessage {
522 fn from(value: lapin::Error) -> Self {
523 AppMessage::RabbitmqError(value)
524 }
525}
526
527#[cfg(feature = "redis")]
528impl From<redis::RedisError> for AppMessage {
529 fn from(value: redis::RedisError) -> Self {
530 AppMessage::RedisError(value)
531 }
532}
533
534#[cfg(feature = "rabbitmq")]
535impl From<deadpool::managed::PoolError<lapin::Error>> for AppMessage {
536 fn from(value: deadpool::managed::PoolError<lapin::Error>) -> Self {
537 AppMessage::RmqPoolError(value)
538 }
539}
540
541#[cfg(feature = "hmac")]
542impl From<hmac::digest::InvalidLength> for AppMessage {
543 fn from(value: hmac::digest::InvalidLength) -> Self {
544 AppMessage::HmacError(value)
545 }
546}
547
548impl From<serde_json::Error> for AppMessage {
549 fn from(value: serde_json::Error) -> Self {
550 AppMessage::SerdeError(value)
551 }
552}
553
554impl From<chrono::ParseError> for AppMessage {
555 fn from(value: chrono::ParseError) -> Self {
556 AppMessage::ChronoParseError(value)
557 }
558}
559
560impl From<std::string::FromUtf8Error> for AppMessage {
561 fn from(value: std::string::FromUtf8Error) -> Self {
562 AppMessage::FromUtf8Error(value)
563 }
564}
565
566impl From<std::str::Utf8Error> for AppMessage {
567 fn from(value: std::str::Utf8Error) -> Self {
568 AppMessage::StrUtf8Error(value)
569 }
570}
571
572#[cfg(feature = "strum")]
573impl From<strum::ParseError> for AppMessage {
574 fn from(value: strum::ParseError) -> Self {
575 AppMessage::StrumParseError(value)
576 }
577}
578
579#[cfg(feature = "multipart")]
580impl From<medullah_multipart::MultipartError> for AppMessage {
581 fn from(value: medullah_multipart::MultipartError) -> Self {
582 AppMessage::MultipartError(value)
583 }
584}
585
586#[cfg(feature = "base64")]
587impl From<base64::DecodeError> for AppMessage {
588 fn from(value: base64::DecodeError) -> Self {
589 AppMessage::Base64Error(value)
590 }
591}
592
593#[cfg(feature = "database")]
594impl From<diesel::result::Error> for AppMessage {
595 fn from(value: diesel::result::Error) -> Self {
596 AppMessage::DatabaseError(value)
597 }
598}
599
600#[cfg(feature = "database")]
601impl From<AppMessage> for diesel::result::Error {
602 fn from(value: AppMessage) -> Self {
603 use diesel::result::Error as DieselError;
604
605 match value {
606 AppMessage::EntityNotFound(_) => diesel::result::Error::NotFound,
607 AppMessage::DatabaseError(DieselError::DatabaseError(
608 diesel::result::DatabaseErrorKind::UniqueViolation,
609 x,
610 )) => DieselError::DatabaseError(diesel::result::DatabaseErrorKind::UniqueViolation, x),
611 AppMessage::DatabaseError(err) => err,
612 _ => panic!("unhandled app message: {:?}", value),
613 }
614 }
615}
616
617impl AppMessage {
618 pub fn http_result(&self) -> crate::results::HttpResult {
619 Ok(self.http_response())
620 }
621
622 pub fn http_response(&self) -> ntex::web::HttpResponse {
623 send_response(self)
624 }
625
626 pub fn status_code(&self) -> StatusCode {
627 get_status_code(self)
628 }
629
630 pub fn message(&self) -> String {
631 get_message(self)
632 }
633}
634
635impl WebResponseError for AppMessage {
636 fn status_code(&self) -> StatusCode {
637 let code = self.status_code();
638 log::info!("[error-code] {}", code);
639 code
640 }
641
642 fn error_response(&self, _: &HttpRequest) -> ntex::web::HttpResponse {
643 log::info!("[error-body] {}", self);
644 self.http_response()
645 }
646}