diff --git a/axum-extra/src/extract/mod.rs b/axum-extra/src/extract/mod.rs index 4c136b412f..f858338d9c 100644 --- a/axum-extra/src/extract/mod.rs +++ b/axum-extra/src/extract/mod.rs @@ -41,7 +41,10 @@ pub use self::cookie::SignedCookieJar; pub use self::form::{Form, FormRejection}; #[cfg(feature = "query")] -pub use self::query::{OptionalQuery, OptionalQueryRejection, Query, QueryRejection}; +#[allow(deprecated)] +pub use self::query::OptionalQuery; +#[cfg(feature = "query")] +pub use self::query::{OptionalQueryRejection, Query, QueryRejection}; #[cfg(feature = "multipart")] pub use self::multipart::Multipart; diff --git a/axum-extra/src/extract/query.rs b/axum-extra/src/extract/query.rs index 695ea9576b..7c73cec38c 100644 --- a/axum-extra/src/extract/query.rs +++ b/axum-extra/src/extract/query.rs @@ -1,5 +1,5 @@ use axum::{ - extract::FromRequestParts, + extract::{FromRequestParts, OptionalFromRequestParts}, response::{IntoResponse, Response}, Error, }; @@ -96,6 +96,27 @@ where } } +impl OptionalFromRequestParts for Query +where + T: DeserializeOwned, + S: Send + Sync, +{ + type Rejection = QueryRejection; + + async fn from_request_parts( + parts: &mut Parts, + _state: &S, + ) -> Result, Self::Rejection> { + if let Some(query) = parts.uri.query() { + let value = serde_html_form::from_str(query) + .map_err(|err| QueryRejection::FailedToDeserializeQueryString(Error::new(err)))?; + Ok(Some(Self(value))) + } else { + Ok(None) + } + } +} + axum_core::__impl_deref!(Query); /// Rejection used for [`Query`]. @@ -182,9 +203,11 @@ impl std::error::Error for QueryRejection { /// /// [example]: https://github.com/tokio-rs/axum/blob/main/examples/query-params-with-empty-strings/src/main.rs #[cfg_attr(docsrs, doc(cfg(feature = "query")))] +#[deprecated = "Use Option> instead"] #[derive(Debug, Clone, Copy, Default)] pub struct OptionalQuery(pub Option); +#[allow(deprecated)] impl FromRequestParts for OptionalQuery where T: DeserializeOwned, @@ -204,6 +227,7 @@ where } } +#[allow(deprecated)] impl std::ops::Deref for OptionalQuery { type Target = Option; @@ -213,6 +237,7 @@ impl std::ops::Deref for OptionalQuery { } } +#[allow(deprecated)] impl std::ops::DerefMut for OptionalQuery { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { @@ -260,6 +285,7 @@ impl std::error::Error for OptionalQueryRejection { } #[cfg(test)] +#[allow(deprecated)] mod tests { use super::*; use crate::test_helpers::*;