1
- use axum:: {
2
- extract:: FromRequestParts ,
3
- response:: { IntoResponse , Response } ,
4
- Error ,
5
- } ;
6
- use http:: { request:: Parts , StatusCode } ;
1
+ use axum:: extract:: FromRequestParts ;
2
+ use axum_core:: __composite_rejection as composite_rejection;
3
+ use axum_core:: __define_rejection as define_rejection;
4
+ use http:: request:: Parts ;
7
5
use serde:: de:: DeserializeOwned ;
8
- use std:: fmt;
9
6
10
7
/// Extractor that deserializes query strings into some type.
11
8
///
@@ -93,63 +90,27 @@ where
93
90
let deserializer =
94
91
serde_html_form:: Deserializer :: new ( form_urlencoded:: parse ( query. as_bytes ( ) ) ) ;
95
92
let value = serde_path_to_error:: deserialize ( deserializer)
96
- . map_err ( |err| QueryRejection :: FailedToDeserializeQueryString ( Error :: new ( err ) ) ) ?;
93
+ . map_err ( FailedToDeserializeQueryString :: from_err ) ?;
97
94
Ok ( Query ( value) )
98
95
}
99
96
}
100
97
101
98
axum_core:: __impl_deref!( Query ) ;
102
99
103
- /// Rejection used for [`Query`].
104
- ///
105
- /// Contains one variant for each way the [`Query`] extractor can fail.
106
- #[ derive( Debug ) ]
107
- #[ non_exhaustive]
108
- #[ cfg( feature = "query" ) ]
109
- pub enum QueryRejection {
110
- #[ allow( missing_docs) ]
111
- FailedToDeserializeQueryString ( Error ) ,
112
- }
113
-
114
- impl QueryRejection {
115
- /// Get the status code used for this rejection.
116
- pub fn status ( & self ) -> StatusCode {
117
- match self {
118
- Self :: FailedToDeserializeQueryString ( _) => StatusCode :: BAD_REQUEST ,
119
- }
120
- }
121
- }
122
-
123
- impl IntoResponse for QueryRejection {
124
- fn into_response ( self ) -> Response {
125
- let status = self . status ( ) ;
126
- match self {
127
- Self :: FailedToDeserializeQueryString ( inner) => {
128
- let body = format ! ( "Failed to deserialize query string: {inner}" ) ;
129
- axum_core:: __log_rejection!(
130
- rejection_type = Self ,
131
- body_text = body,
132
- status = status,
133
- ) ;
134
- ( status, body) . into_response ( )
135
- }
136
- }
137
- }
138
- }
139
-
140
- impl fmt:: Display for QueryRejection {
141
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
142
- match self {
143
- Self :: FailedToDeserializeQueryString ( inner) => inner. fmt ( f) ,
144
- }
145
- }
100
+ define_rejection ! {
101
+ #[ status = BAD_REQUEST ]
102
+ #[ body = "Failed to deserialize query string" ]
103
+ /// Rejection type used if the [`Query`] extractor is unable to
104
+ /// deserialize the query string into the target type.
105
+ pub struct FailedToDeserializeQueryString ( Error ) ;
146
106
}
147
107
148
- impl std:: error:: Error for QueryRejection {
149
- fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
150
- match self {
151
- Self :: FailedToDeserializeQueryString ( inner) => Some ( inner) ,
152
- }
108
+ composite_rejection ! {
109
+ /// Rejection used for [`Query`].
110
+ ///
111
+ /// Contains one variant for each way the [`Query`] extractor can fail.
112
+ pub enum QueryRejection {
113
+ FailedToDeserializeQueryString ,
153
114
}
154
115
}
155
116
@@ -207,9 +168,8 @@ where
207
168
if let Some ( query) = parts. uri . query ( ) {
208
169
let deserializer =
209
170
serde_html_form:: Deserializer :: new ( form_urlencoded:: parse ( query. as_bytes ( ) ) ) ;
210
- let value = serde_path_to_error:: deserialize ( deserializer) . map_err ( |err| {
211
- OptionalQueryRejection :: FailedToDeserializeQueryString ( Error :: new ( err) )
212
- } ) ?;
171
+ let value = serde_path_to_error:: deserialize ( deserializer)
172
+ . map_err ( FailedToDeserializeQueryString :: from_err) ?;
213
173
Ok ( OptionalQuery ( Some ( value) ) )
214
174
} else {
215
175
Ok ( OptionalQuery ( None ) )
@@ -233,42 +193,12 @@ impl<T> std::ops::DerefMut for OptionalQuery<T> {
233
193
}
234
194
}
235
195
236
- /// Rejection used for [`OptionalQuery`].
237
- ///
238
- /// Contains one variant for each way the [`OptionalQuery`] extractor can fail.
239
- #[ derive( Debug ) ]
240
- #[ non_exhaustive]
241
- #[ cfg( feature = "query" ) ]
242
- pub enum OptionalQueryRejection {
243
- #[ allow( missing_docs) ]
244
- FailedToDeserializeQueryString ( Error ) ,
245
- }
246
-
247
- impl IntoResponse for OptionalQueryRejection {
248
- fn into_response ( self ) -> Response {
249
- match self {
250
- Self :: FailedToDeserializeQueryString ( inner) => (
251
- StatusCode :: BAD_REQUEST ,
252
- format ! ( "Failed to deserialize query string: {inner}" ) ,
253
- )
254
- . into_response ( ) ,
255
- }
256
- }
257
- }
258
-
259
- impl fmt:: Display for OptionalQueryRejection {
260
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
261
- match self {
262
- Self :: FailedToDeserializeQueryString ( inner) => inner. fmt ( f) ,
263
- }
264
- }
265
- }
266
-
267
- impl std:: error:: Error for OptionalQueryRejection {
268
- fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
269
- match self {
270
- Self :: FailedToDeserializeQueryString ( inner) => Some ( inner) ,
271
- }
196
+ composite_rejection ! {
197
+ /// Rejection used for [`OptionalQuery`].
198
+ ///
199
+ /// Contains one variant for each way the [`OptionalQuery`] extractor can fail.
200
+ pub enum OptionalQueryRejection {
201
+ FailedToDeserializeQueryString ,
272
202
}
273
203
}
274
204
@@ -279,6 +209,7 @@ mod tests {
279
209
use axum:: routing:: { get, post} ;
280
210
use axum:: Router ;
281
211
use http:: header:: CONTENT_TYPE ;
212
+ use http:: StatusCode ;
282
213
use serde:: Deserialize ;
283
214
284
215
#[ tokio:: test]
0 commit comments