Skip to main content

axum_error_sets/
codes.rs

1//! Wrapper types for every 4xx and 5xx HTTP status code.
2//!
3//! Each type is a tuple struct `Code<T = ()>(pub T)`. The wrapped `T` is the response body and
4//! must implement [`IntoResponse`] to be used in an [`ApiResponse`]. For example:
5//! - `NotFound` (that is, `NotFound<()>`) is a 404 with an empty body.
6//! - `NotFound<String>` is a 404 with a plain-text body.
7//! - `NotFound<Json<MyError>>` is a 404 with a JSON body.
8//!
9//! Every type implements [`StatusProvider`], `From<T>`, and `Deref`/`DerefMut` to `T`.
10
11use super::*;
12
13macro_rules! define_codes {
14(
15    $(
16        $(#[$meta:meta])*
17        $(fn $fn_name:ident ();)?
18        code $name:ident => $status:expr;
19    )*
20) => {
21    $(
22        $(#[$meta])*
23        #[derive(Debug, Clone, Copy, Default)]
24        pub struct $name<T = ()>(pub T);
25
26        impl<T> StatusProvider for $name<T> {
27            const STATUS_CODE: StatusCode = $status;
28            type Inner = T;
29            type WithInner<R> = $name<R>;
30            fn into_inner(self) -> Self::Inner {
31                self.0
32            }
33        }
34
35        impl<T, S> From<$name<T>> for ApiResponse<S>
36        where
37            S: Contains<$name<T>>,
38            $name<T>: StatusProvider<Inner: IntoResponse>,
39        {
40            fn from(err: $name<T>) -> Self {
41                ApiResponse::new(err)
42            }
43        }
44
45        impl<T> From<T> for $name<T> {
46            fn from(inner: T) -> Self {
47                Self(inner)
48            }
49        }
50
51        impl<T> std::ops::Deref for $name<T> {
52            type Target = T;
53
54            fn deref(&self) -> &Self::Target {
55                &self.0
56            }
57        }
58
59        impl<T> std::ops::DerefMut for $name<T> {
60            fn deref_mut(&mut self) -> &mut Self::Target {
61                &mut self.0
62            }
63        }
64    )*
65};
66}
67
68define_codes!(
69    /// 400 Bad Request
70    fn map_bad_request();
71    code BadRequest => StatusCode::BAD_REQUEST;
72
73    /// 401 Unauthorized
74    fn map_unauthorized();
75    code Unauthorized => StatusCode::UNAUTHORIZED;
76
77    /// 402 Payment Required
78    fn map_payment_required();
79    code PaymentRequired => StatusCode::PAYMENT_REQUIRED;
80
81    /// 403 Forbidden
82    fn map_forbidden();
83    code Forbidden => StatusCode::FORBIDDEN;
84
85    /// 404 Not Found
86    fn map_not_found();
87    code NotFound => StatusCode::NOT_FOUND;
88
89    /// 405 Method Not Allowed
90    fn map_method_not_allowed();
91    code MethodNotAllowed => StatusCode::METHOD_NOT_ALLOWED;
92
93    /// 406 Not Acceptable
94    fn map_not_acceptable();
95    code NotAcceptable => StatusCode::NOT_ACCEPTABLE;
96
97    /// 407 Proxy Authentication Required
98    fn map_proxy_authentication_required();
99    code ProxyAuthenticationRequired => StatusCode::PROXY_AUTHENTICATION_REQUIRED;
100
101    /// 408 Request Timeout
102    fn map_request_timeout();
103    code RequestTimeout => StatusCode::REQUEST_TIMEOUT;
104
105    /// 409 Conflict
106    fn map_conflict();
107    code Conflict => StatusCode::CONFLICT;
108
109    /// 410 Gone
110    fn map_gone();
111    code Gone => StatusCode::GONE;
112
113    /// 411 Length Required
114    fn map_length_required();
115    code LengthRequired => StatusCode::LENGTH_REQUIRED;
116
117    /// 412 Precondition Failed
118    fn map_precondition_failed();
119    code PreconditionFailed => StatusCode::PRECONDITION_FAILED;
120
121    /// 413 Payload Too Large
122    fn map_payload_too_large();
123    code PayloadTooLarge => StatusCode::PAYLOAD_TOO_LARGE;
124
125    /// 414 URI Too Long
126    fn map_uri_too_long();
127    code UriTooLong => StatusCode::URI_TOO_LONG;
128
129    /// 415 Unsupported Media Type
130    fn map_unsupported_media_type();
131    code UnsupportedMediaType => StatusCode::UNSUPPORTED_MEDIA_TYPE;
132
133    /// 416 Range Not Satisfiable
134    fn map_range_not_satisfiable();
135    code RangeNotSatisfiable => StatusCode::RANGE_NOT_SATISFIABLE;
136
137    /// 417 Expectation Failed
138    fn map_expectation_failed();
139    code ExpectationFailed => StatusCode::EXPECTATION_FAILED;
140
141    /// 418 I'm a teapot
142    fn map_im_a_teapot();
143    code ImATeapot => StatusCode::IM_A_TEAPOT;
144
145    /// 421 Misdirected Request
146    fn map_misdirected_request();
147    code MisdirectedRequest => StatusCode::MISDIRECTED_REQUEST;
148
149    /// 422 Unprocessable Entity
150    fn map_unprocessable_entity();
151    code UnprocessableEntity => StatusCode::UNPROCESSABLE_ENTITY;
152
153    /// 423 Locked
154    fn map_locked();
155    code Locked => StatusCode::LOCKED;
156
157    /// 424 Failed Dependency
158    fn map_failed_dependency();
159    code FailedDependency => StatusCode::FAILED_DEPENDENCY;
160
161    /// 425 Too Early
162    fn map_too_early();
163    code TooEarly => StatusCode::TOO_EARLY;
164
165    /// 426 Upgrade Required
166    fn map_upgrade_required();
167    code UpgradeRequired => StatusCode::UPGRADE_REQUIRED;
168
169    /// 428 Precondition Required
170    fn map_precondition_required();
171    code PreconditionRequired => StatusCode::PRECONDITION_REQUIRED;
172
173    /// 429 Too Many Requests
174    fn map_too_many_requests();
175    code TooManyRequests => StatusCode::TOO_MANY_REQUESTS;
176
177    /// 431 Request Header Fields Too Large
178    fn map_request_header_fields_too_large();
179    code RequestHeaderFieldsTooLarge => StatusCode::REQUEST_HEADER_FIELDS_TOO_LARGE;
180
181    /// 451 Unavailable For Legal Reasons
182    fn map_unavailable_for_legal_reasons();
183    code UnavailableForLegalReasons => StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS;
184
185    /// 500 Internal Server Error
186    fn map_internal();
187    code Internal => StatusCode::INTERNAL_SERVER_ERROR;
188
189    /// 501 Not Implemented
190    fn map_not_implemented();
191    code NotImplemented => StatusCode::NOT_IMPLEMENTED;
192
193    /// 502 Bad Gateway
194    fn map_bad_gateway();
195    code BadGateway => StatusCode::BAD_GATEWAY;
196
197    /// 503 Service Unavailable
198    fn map_service_unavailable();
199    code ServiceUnavailable => StatusCode::SERVICE_UNAVAILABLE;
200
201    /// 504 Gateway Timeout
202    fn map_gateway_timeout();
203    code GatewayTimeout => StatusCode::GATEWAY_TIMEOUT;
204
205    /// 505 HTTP Version Not Supported
206    fn map_http_version_not_supported();
207    code HttpVersionNotSupported => StatusCode::HTTP_VERSION_NOT_SUPPORTED;
208
209    /// 506 Variant Also Negotiates
210    fn map_variant_also_negotiates();
211    code VariantAlsoNegotiates => StatusCode::VARIANT_ALSO_NEGOTIATES;
212
213    /// 507 Insufficient Storage
214    fn map_insufficient_storage();
215    code InsufficientStorage => StatusCode::INSUFFICIENT_STORAGE;
216
217    /// 508 Loop Detected
218    fn map_loop_detected();
219    code LoopDetected => StatusCode::LOOP_DETECTED;
220
221    /// 510 Not Extended
222    fn map_not_extended();
223    code NotExtended => StatusCode::NOT_EXTENDED;
224
225    /// 511 Network Authentication Required
226    fn map_network_authentication_required();
227    code NetworkAuthenticationRequired => StatusCode::NETWORK_AUTHENTICATION_REQUIRED;
228);