Add axum_extra::extract::Query::try_from_uri (#3460)

`axum::extract::Query` has a try_from_uri, which is useful for testing. This adds the same function to `axum_extra::extract::Query`.
This commit is contained in:
Joel Uckelman 2025-09-08 09:18:31 +01:00 committed by GitHub
parent 64ae48347e
commit 5d5ba01be9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -1,7 +1,7 @@
use axum::extract::FromRequestParts;
use axum_core::__composite_rejection as composite_rejection;
use axum_core::__define_rejection as define_rejection;
use http::request::Parts;
use http::{request::Parts, Uri};
use serde::de::DeserializeOwned;
/// Extractor that deserializes query strings into some type.
@ -95,6 +95,37 @@ where
}
}
impl<T> Query<T>
where
T: DeserializeOwned,
{
/// Attempts to construct a [`Query`] from a reference to a [`Uri`].
///
/// # Example
/// ```
/// use axum_extra::extract::Query;
/// use http::Uri;
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
/// struct ExampleParams {
/// foo: String,
/// bar: u32,
/// }
///
/// let uri: Uri = "http://example.com/path?foo=hello&bar=42".parse().unwrap();
/// let result: Query<ExampleParams> = Query::try_from_uri(&uri).unwrap();
/// assert_eq!(result.foo, String::from("hello"));
/// assert_eq!(result.bar, 42);
/// ```
pub fn try_from_uri(value: &Uri) -> Result<Self, QueryRejection> {
let query = value.query().unwrap_or_default();
let params =
serde_html_form::from_str(query).map_err(FailedToDeserializeQueryString::from_err)?;
Ok(Self(params))
}
}
axum_core::__impl_deref!(Query);
define_rejection! {
@ -338,4 +369,34 @@ mod tests {
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
}
#[test]
fn test_try_from_uri() {
#[derive(Deserialize)]
struct TestQueryParams {
foo: Vec<String>,
bar: u32,
}
let uri: Uri = "http://example.com/path?foo=hello&bar=42&foo=goodbye"
.parse()
.unwrap();
let result: Query<TestQueryParams> = Query::try_from_uri(&uri).unwrap();
assert_eq!(result.foo, [String::from("hello"), String::from("goodbye")]);
assert_eq!(result.bar, 42);
}
#[test]
fn test_try_from_uri_with_invalid_query() {
#[derive(Deserialize)]
struct TestQueryParams {
_foo: String,
_bar: u32,
}
let uri: Uri = "http://example.com/path?foo=hello&bar=invalid"
.parse()
.unwrap();
let result: Result<Query<TestQueryParams>, _> = Query::try_from_uri(&uri);
assert!(result.is_err());
}
}