Skip to content

Commit 9eb731f

Browse files
committed
Remove OptionalFromRequestParts impl for Query
1 parent a7aaa1d commit 9eb731f

File tree

5 files changed

+9
-79
lines changed

5 files changed

+9
-79
lines changed

axum-extra/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning].
77

88
# Unreleased
99

10+
- **breaking:** Remove `OptionalFromRequestParts` impl for `Query` ([#3088])
11+
12+
[#3088]: https://github.com/tokio-rs/axum/pull/3088
13+
1014
# 0.10.0
1115

1216
## rc.1

axum-extra/src/extract/query.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use axum::{
2-
extract::{FromRequestParts, OptionalFromRequestParts},
2+
extract::FromRequestParts,
33
response::{IntoResponse, Response},
44
Error,
55
};
@@ -18,19 +18,6 @@ use std::fmt;
1818
/// with the `multiple` attribute. Those values can be collected into a `Vec` or other sequential
1919
/// container.
2020
///
21-
/// # `Option<Query<T>>` behavior
22-
///
23-
/// If `Query<T>` itself is used as an extractor and there is no query string in
24-
/// the request URL, `T`'s `Deserialize` implementation is called on an empty
25-
/// string instead.
26-
///
27-
/// You can avoid this by using `Option<Query<T>>`, which gives you `None` in
28-
/// the case that there is no query string in the request URL.
29-
///
30-
/// Note that an empty query string is not the same as no query string, that is
31-
/// `https://example.org/` and `https://example.org/?` are not treated the same
32-
/// in this case.
33-
///
3421
/// # Example
3522
///
3623
/// ```rust,no_run
@@ -109,27 +96,6 @@ where
10996
}
11097
}
11198

112-
impl<T, S> OptionalFromRequestParts<S> for Query<T>
113-
where
114-
T: DeserializeOwned,
115-
S: Send + Sync,
116-
{
117-
type Rejection = QueryRejection;
118-
119-
async fn from_request_parts(
120-
parts: &mut Parts,
121-
_state: &S,
122-
) -> Result<Option<Self>, Self::Rejection> {
123-
if let Some(query) = parts.uri.query() {
124-
let value = serde_html_form::from_str(query)
125-
.map_err(|err| QueryRejection::FailedToDeserializeQueryString(Error::new(err)))?;
126-
Ok(Some(Self(value)))
127-
} else {
128-
Ok(None)
129-
}
130-
}
131-
}
132-
13399
axum_core::__impl_deref!(Query);
134100

135101
/// Rejection used for [`Query`].

axum/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
- **breaking:** `axum::extract::ws::Message` now uses `Bytes` in place of `Vec<u8>`,
1111
and a new `Utf8Bytes` type in place of `String`, for its variants ([#3078])
12+
- **breaking:** Remove `OptionalFromRequestParts` impl for `Query` ([#3088])
1213
- **changed:** Upgraded `tokio-tungstenite` to 0.26 ([#3078])
1314

1415
[#3078]: https://github.com/tokio-rs/axum/pull/3078
16+
[#3088]: https://github.com/tokio-rs/axum/pull/3088
1517

1618
# 0.8.0
1719

axum/src/docs/extract.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,10 @@ struct Pagination {
108108
per_page: usize,
109109
}
110110
111-
impl Default for Pagination {
112-
fn default() -> Self {
113-
Self { page: 1, per_page: 30 }
114-
}
115-
}
116-
117111
async fn get_user_things(
118112
Path(user_id): Path<Uuid>,
119-
pagination: Option<Query<Pagination>>,
113+
Query(pagination): Query<Pagination>,
120114
) {
121-
let Query(pagination) = pagination.unwrap_or_default();
122-
123115
// ...
124116
}
125117
# let _: Router = app;

axum/src/extract/query.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
1-
use super::{rejection::*, FromRequestParts, OptionalFromRequestParts};
1+
use super::{rejection::*, FromRequestParts};
22
use http::{request::Parts, Uri};
33
use serde::de::DeserializeOwned;
44

55
/// Extractor that deserializes query strings into some type.
66
///
77
/// `T` is expected to implement [`serde::Deserialize`].
88
///
9-
/// # `Option<Query<T>>` behavior
10-
///
11-
/// If `Query<T>` itself is used as an extractor and there is no query string in
12-
/// the request URL, `T`'s `Deserialize` implementation is called on an empty
13-
/// string instead.
14-
///
15-
/// You can avoid this by using `Option<Query<T>>`, which gives you `None` in
16-
/// the case that there is no query string in the request URL.
17-
///
18-
/// Note that an empty query string is not the same as no query string, that is
19-
/// `https://example.org/` and `https://example.org/?` are not treated the same
20-
/// in this case.
21-
///
229
/// # Examples
2310
///
2411
/// ```rust,no_run
@@ -75,27 +62,6 @@ where
7562
}
7663
}
7764

78-
impl<T, S> OptionalFromRequestParts<S> for Query<T>
79-
where
80-
T: DeserializeOwned,
81-
S: Send + Sync,
82-
{
83-
type Rejection = QueryRejection;
84-
85-
async fn from_request_parts(
86-
parts: &mut Parts,
87-
_state: &S,
88-
) -> Result<Option<Self>, Self::Rejection> {
89-
if let Some(query) = parts.uri.query() {
90-
let value = serde_urlencoded::from_str(query)
91-
.map_err(FailedToDeserializeQueryString::from_err)?;
92-
Ok(Some(Self(value)))
93-
} else {
94-
Ok(None)
95-
}
96-
}
97-
}
98-
9965
impl<T> Query<T>
10066
where
10167
T: DeserializeOwned,

0 commit comments

Comments
 (0)