mirror of
https://github.com/tokio-rs/axum.git
synced 2025-09-27 04:50:31 +00:00
Add axum::extract::Query::try_from_uri
(#2058)
Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
This commit is contained in:
parent
74758f61c8
commit
8b36dd6d83
@ -12,9 +12,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
# 0.6.18 (30. April, 2023)
|
||||
|
||||
- **fixed:** Don't remove the `Sec-WebSocket-Key` header in `WebSocketUpgrade` ([#1972])
|
||||
- **added:** Add `axum::extract::Query::try_from_uri` ([#2058])
|
||||
- **added:** Implement `IntoResponse` for `Box<str>` and `Box<[u8]>` ([#2035])
|
||||
|
||||
[#1972]: https://github.com/tokio-rs/axum/pull/1972
|
||||
[#2058]: https://github.com/tokio-rs/axum/pull/2058
|
||||
|
||||
# 0.6.17 (25. April, 2023)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use super::{rejection::*, FromRequestParts};
|
||||
use async_trait::async_trait;
|
||||
use http::request::Parts;
|
||||
use http::{request::Parts, Uri};
|
||||
use serde::de::DeserializeOwned;
|
||||
|
||||
/// Extractor that deserializes query strings into some type.
|
||||
@ -57,10 +57,38 @@ where
|
||||
type Rejection = QueryRejection;
|
||||
|
||||
async fn from_request_parts(parts: &mut Parts, _state: &S) -> Result<Self, Self::Rejection> {
|
||||
let query = parts.uri.query().unwrap_or_default();
|
||||
let value =
|
||||
Self::try_from_uri(&parts.uri)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Query<T>
|
||||
where
|
||||
T: DeserializeOwned,
|
||||
{
|
||||
/// Attempts to construct a [`Query`] from a reference to a [`Uri`].
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use axum::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_urlencoded::from_str(query).map_err(FailedToDeserializeQueryString::from_err)?;
|
||||
Ok(Query(value))
|
||||
Ok(Query(params))
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,4 +164,32 @@ mod tests {
|
||||
let res = client.get("/?n=hi").send().await;
|
||||
assert_eq!(res.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_uri() {
|
||||
#[derive(Deserialize)]
|
||||
struct TestQueryParams {
|
||||
foo: String,
|
||||
bar: u32,
|
||||
}
|
||||
let uri: Uri = "http://example.com/path?foo=hello&bar=42".parse().unwrap();
|
||||
let result: Query<TestQueryParams> = Query::try_from_uri(&uri).unwrap();
|
||||
assert_eq!(result.foo, String::from("hello"));
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user