mirror of
https://github.com/tokio-rs/axum.git
synced 2024-12-29 15:49:16 +01:00
Add axum::extract::Query::try_from_uri
(#2058)
Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
This commit is contained in:
parent
cc9629fe88
commit
0ed02a9a46
2 changed files with 62 additions and 4 deletions
|
@ -53,6 +53,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- **breaking:** Only inherit fallbacks for routers nested with `Router::nest`.
|
||||
Routers nested with `Router::nest_service` will no longer inherit fallbacks ([#1956])
|
||||
- **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])
|
||||
|
||||
[#1664]: https://github.com/tokio-rs/axum/pull/1664
|
||||
|
@ -64,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
[#1868]: https://github.com/tokio-rs/axum/pull/1868
|
||||
[#1956]: https://github.com/tokio-rs/axum/pull/1956
|
||||
[#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.
|
||||
|
@ -55,10 +55,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))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,4 +165,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…
Reference in a new issue