From b9db657134263a444336d6f99624bb0656809752 Mon Sep 17 00:00:00 2001 From: Tobias Bieniek Date: Thu, 26 Dec 2024 23:12:47 +0100 Subject: [PATCH] axum-extra/form: Add `FailedToDeserializeFormBody` rejection variant This brings the `From` extractor from `axum-extra` closer to the one from `axum`. --- axum-extra/src/extract/form.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/axum-extra/src/extract/form.rs b/axum-extra/src/extract/form.rs index f31c54998e..454c50a727 100644 --- a/axum-extra/src/extract/form.rs +++ b/axum-extra/src/extract/form.rs @@ -51,14 +51,22 @@ where type Rejection = FormRejection; async fn from_request(req: Request, _state: &S) -> Result { + let is_get_or_head = + req.method() == http::Method::GET || req.method() == http::Method::HEAD; + let RawForm(bytes) = req.extract().await?; let deserializer = serde_html_form::Deserializer::new(form_urlencoded::parse(&bytes)); - let value = serde_path_to_error::deserialize::<_, T>(deserializer) - .map_err(FailedToDeserializeForm::from_err)?; - - Ok(Self(value)) + serde_path_to_error::deserialize::<_, T>(deserializer) + .map(Self) + .map_err(|err| { + if is_get_or_head { + FailedToDeserializeForm::from_err(err).into() + } else { + FailedToDeserializeFormBody::from_err(err).into() + } + }) } } @@ -70,6 +78,14 @@ define_rejection! { pub struct FailedToDeserializeForm(Error); } +define_rejection! { + #[status = UNPROCESSABLE_ENTITY] + #[body = "Failed to deserialize form body"] + /// Rejection type used if the [`Form`](Form) extractor is unable to + /// deserialize the form body into the target type. + pub struct FailedToDeserializeFormBody(Error); +} + composite_rejection! { /// Rejection used for [`Form`]. /// @@ -77,6 +93,7 @@ composite_rejection! { pub enum FormRejection { RawFormRejection, FailedToDeserializeForm, + FailedToDeserializeFormBody, } } @@ -146,10 +163,10 @@ mod tests { .header(CONTENT_TYPE, APPLICATION_WWW_FORM_URLENCODED.as_ref()) .body("a=false") .await; - assert_eq!(res.status(), StatusCode::BAD_REQUEST); + assert_eq!(res.status(), StatusCode::UNPROCESSABLE_ENTITY); assert_eq!( res.text().await, - "Failed to deserialize form: a: invalid digit found in string" + "Failed to deserialize form body: a: invalid digit found in string" ); } }