mj_controller/server/api/
failure.rs1use super::*;
2
3#[derive(Debug)]
10pub struct ApiFailure {
11 pub status: StatusCode,
12 pub message: String,
13}
14
15impl ApiFailure {
16 pub fn new(status: StatusCode, message: impl Into<String>) -> Self {
17 Self {
18 status,
19 message: message.into(),
20 }
21 }
22
23 pub fn bad_request(message: impl Into<String>) -> Self {
24 Self::new(StatusCode::BAD_REQUEST, message)
25 }
26
27 pub fn conflict(message: impl Into<String>) -> Self {
28 Self::new(StatusCode::CONFLICT, message)
29 }
30
31 pub fn not_found(message: impl Into<String>) -> Self {
32 Self::new(StatusCode::NOT_FOUND, message)
33 }
34
35 pub fn unavailable(message: impl Into<String>) -> Self {
36 Self::new(StatusCode::SERVICE_UNAVAILABLE, message)
37 }
38}
39
40impl std::fmt::Display for ApiFailure {
41 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
42 write!(formatter, "{}: {}", self.status, self.message)
43 }
44}
45
46impl From<ApiError> for ApiFailure {
47 fn from(error: ApiError) -> Self {
48 Self::new(error.status, error.message)
49 }
50}
51
52impl From<anyhow::Error> for ApiFailure {
53 fn from(error: anyhow::Error) -> Self {
54 if let Some(refusal) = mj_core::refusal::Refusal::of(&error) {
55 return match refusal.kind() {
56 mj_core::refusal::RefusalKind::Precondition => Self::conflict(refusal.message()),
57 mj_core::refusal::RefusalKind::Unusable => Self::bad_request(refusal.message()),
58 };
59 }
60 Self::new(StatusCode::INTERNAL_SERVER_ERROR, format!("{error:#}"))
61 }
62}
63
64#[derive(Debug, Serialize)]
65pub(super) struct FailureBody {
66 pub(super) error: String,
67}
68
69impl IntoResponse for ApiFailure {
70 fn into_response(self) -> Response {
71 (
72 self.status,
73 Json(FailureBody {
74 error: self.message,
75 }),
76 )
77 .into_response()
78 }
79}
80
81