axum_handler_error/
lib.rs1use axum::{
2 http::StatusCode,
3 response::{IntoResponse, Response},
4 Json,
5};
6
7pub enum Error {
10 InvalidArgs(Vec<String>),
12
13 NotFound(String),
15
16 Conflict(String),
18
19 InvalidEntity(Vec<String>),
21
22 Internal,
24}
25
26impl Error {
27 pub fn invalid_args<T>(error: T) -> Self
29 where
30 T: ToString,
31 {
32 let errors = vec![error.to_string()];
33 Error::InvalidArgs(errors)
34 }
35
36 pub fn invalid_args_all<I, T>(errors: I) -> Self
38 where
39 I: IntoIterator<Item = T>,
40 T: ToString,
41 {
42 let errors = errors.into_iter().map(|e| e.to_string()).collect();
43 Error::InvalidArgs(errors)
44 }
45
46 pub fn not_found<T>(error: T) -> Self
48 where
49 T: ToString,
50 {
51 Error::NotFound(error.to_string())
52 }
53
54 pub fn conflict<T>(error: T) -> Self
56 where
57 T: ToString,
58 {
59 Error::Conflict(error.to_string())
60 }
61
62 pub fn invalid_entity<T>(error: T) -> Self
64 where
65 T: ToString,
66 {
67 let errors = vec![error.to_string()];
68 Error::InvalidEntity(errors)
69 }
70
71 pub fn invalid_entity_all<I, T>(errors: I) -> Self
73 where
74 I: IntoIterator<Item = T>,
75 T: ToString,
76 {
77 let errors = errors.into_iter().map(|e| e.to_string()).collect();
78 Error::InvalidEntity(errors)
79 }
80}
81
82impl IntoResponse for Error {
83 fn into_response(self) -> Response {
84 match self {
85 Error::InvalidArgs(errors) => {
86 let errors = Json(
87 errors
88 .into_iter()
89 .map(|e| e.to_string())
90 .collect::<Vec<_>>(),
91 );
92 (StatusCode::BAD_REQUEST, errors).into_response()
93 }
94
95 Error::NotFound(error) => {
96 let errors = Json(vec![error.to_string()]);
97 (StatusCode::NOT_FOUND, errors).into_response()
98 }
99
100 Error::Conflict(error) => {
101 let errors = Json(vec![error.to_string()]);
102 (StatusCode::CONFLICT, errors).into_response()
103 }
104
105 Error::InvalidEntity(errors) => {
106 let errors = Json(
107 errors
108 .into_iter()
109 .map(|e| e.to_string())
110 .collect::<Vec<_>>(),
111 );
112 (StatusCode::UNPROCESSABLE_ENTITY, errors).into_response()
113 }
114
115 Error::Internal => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
116 }
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123 use anyhow::anyhow;
124 use std::iter;
125 use thiserror::Error;
126
127 #[derive(Debug, Error)]
128 #[error("test")]
129 struct TestError;
130
131 #[test]
132 fn test_invalid_args() {
133 Error::invalid_args("test").into_response();
134 Error::invalid_args(anyhow!("test")).into_response();
135 let response = Error::invalid_args(TestError).into_response();
136 assert_eq!(response.status(), StatusCode::BAD_REQUEST);
137 }
138
139 #[test]
140 fn test_invalid_args_all() {
141 Error::invalid_args_all(vec!["test"]).into_response();
142 let response = Error::invalid_args_all(iter::once(TestError)).into_response();
143 assert_eq!(response.status(), StatusCode::BAD_REQUEST);
144 }
145
146 #[test]
147 fn test_not_found() {
148 Error::not_found("test").into_response();
149 Error::not_found(anyhow!("test")).into_response();
150 let response = Error::not_found(TestError).into_response();
151 assert_eq!(response.status(), StatusCode::NOT_FOUND);
152 }
153
154 #[test]
155 fn test_conflict() {
156 Error::conflict("test").into_response();
157 Error::conflict(anyhow!("test")).into_response();
158 let response = Error::conflict(TestError).into_response();
159 assert_eq!(response.status(), StatusCode::CONFLICT);
160 }
161
162 #[test]
163 fn test_invalid_entity() {
164 Error::invalid_entity("test").into_response();
165 Error::invalid_entity(anyhow!("test")).into_response();
166 let response = Error::invalid_entity(TestError).into_response();
167 assert_eq!(response.status(), StatusCode::UNPROCESSABLE_ENTITY);
168 }
169
170 #[test]
171 fn test_invalid_entity_all() {
172 Error::invalid_entity_all(vec!["test"]).into_response();
173 let response = Error::invalid_entity_all(iter::once(TestError)).into_response();
174 assert_eq!(response.status(), StatusCode::UNPROCESSABLE_ENTITY);
175 }
176
177 #[test]
178 fn test_internal() {
179 let response = Error::Internal.into_response();
180 assert_eq!(response.status(), StatusCode::INTERNAL_SERVER_ERROR);
181 }
182}