mirror of
https://github.com/tokio-rs/axum.git
synced 2026-08-27 00:00:24 +02:00
axum: Use serde_html_form for Query and Form (#3594)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
#![allow(deprecated)]
|
||||
|
||||
use axum::extract::rejection::RawFormRejection;
|
||||
use axum::{
|
||||
extract::{FromRequest, RawForm, Request},
|
||||
@@ -12,31 +14,16 @@ use serde_core::de::DeserializeOwned;
|
||||
///
|
||||
/// `T` is expected to implement [`serde::Deserialize`].
|
||||
///
|
||||
/// # Differences from `axum::extract::Form`
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This extractor uses [`serde_html_form`] under-the-hood which supports multi-value items. These
|
||||
/// are sent by multiple `<input>` attributes of the same name (e.g. checkboxes) and `<select>`s
|
||||
/// with the `multiple` attribute. Those values can be collected into a `Vec` or other sequential
|
||||
/// container.
|
||||
/// This extractor used to use a different deserializer under-the-hood but that
|
||||
/// is no longer the case. Now it only uses an older version of the same
|
||||
/// deserializer, purely for ease of transition to the latest version.
|
||||
/// Before switching to `axum::extract::Form`, it is recommended to read the
|
||||
/// [changelog for `serde_html_form v0.3.0`][changelog].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use axum_extra::extract::Form;
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// struct Payload {
|
||||
/// #[serde(rename = "value")]
|
||||
/// values: Vec<String>,
|
||||
/// }
|
||||
///
|
||||
/// async fn accept_form(Form(payload): Form<Payload>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`serde_html_form`]: https://crates.io/crates/serde_html_form
|
||||
/// [changelog]: https://github.com/jplatte/serde_html_form/blob/main/CHANGELOG.md#030
|
||||
#[deprecated = "see documentation"]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
#[cfg(feature = "form")]
|
||||
pub struct Form<T>(pub T);
|
||||
@@ -90,6 +77,7 @@ composite_rejection! {
|
||||
/// Rejection used for [`Form`].
|
||||
///
|
||||
/// Contains one variant for each way the [`Form`] extractor can fail.
|
||||
#[deprecated = "because Form is deprecated"]
|
||||
pub enum FormRejection {
|
||||
RawFormRejection,
|
||||
FailedToDeserializeForm,
|
||||
|
||||
@@ -52,11 +52,13 @@ pub use self::cookie::PrivateCookieJar;
|
||||
pub use self::cookie::SignedCookieJar;
|
||||
|
||||
#[cfg(feature = "form")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::form::{Form, FormRejection};
|
||||
|
||||
#[cfg(feature = "query")]
|
||||
pub use self::query::OptionalQuery;
|
||||
#[cfg(feature = "query")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::query::{OptionalQueryRejection, Query, QueryRejection};
|
||||
|
||||
#[cfg(feature = "multipart")]
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(deprecated)]
|
||||
|
||||
use axum_core::__composite_rejection as composite_rejection;
|
||||
use axum_core::__define_rejection as define_rejection;
|
||||
use axum_core::extract::FromRequestParts;
|
||||
@@ -8,72 +10,16 @@ use serde_core::de::DeserializeOwned;
|
||||
///
|
||||
/// `T` is expected to implement [`serde::Deserialize`].
|
||||
///
|
||||
/// # Differences from `axum::extract::Query`
|
||||
/// # Deprecated
|
||||
///
|
||||
/// This extractor uses [`serde_html_form`] under-the-hood which supports multi-value items. These
|
||||
/// are sent by multiple `<input>` attributes of the same name (e.g. checkboxes) and `<select>`s
|
||||
/// with the `multiple` attribute. Those values can be collected into a `Vec` or other sequential
|
||||
/// container.
|
||||
/// This extractor used to use a different deserializer under-the-hood but that
|
||||
/// is no longer the case. Now it only uses an older version of the same
|
||||
/// deserializer, purely for ease of transition to the latest version.
|
||||
/// Before switching to `axum::extract::Form`, it is recommended to read the
|
||||
/// [changelog for `serde_html_form v0.3.0`][changelog].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use axum::{routing::get, Router};
|
||||
/// use axum_extra::extract::Query;
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// struct Pagination {
|
||||
/// page: usize,
|
||||
/// per_page: usize,
|
||||
/// }
|
||||
///
|
||||
/// // This will parse query strings like `?page=2&per_page=30` into `Pagination`
|
||||
/// // structs.
|
||||
/// async fn list_things(pagination: Query<Pagination>) {
|
||||
/// let pagination: Pagination = pagination.0;
|
||||
///
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// let app = Router::new().route("/list_things", get(list_things));
|
||||
/// # let _: Router = app;
|
||||
/// ```
|
||||
///
|
||||
/// If the query string cannot be parsed it will reject the request with a `400
|
||||
/// Bad Request` response.
|
||||
///
|
||||
/// For handling values being empty vs missing see the [query-params-with-empty-strings][example]
|
||||
/// example.
|
||||
///
|
||||
/// [example]: https://github.com/tokio-rs/axum/blob/main/examples/query-params-with-empty-strings/src/main.rs
|
||||
///
|
||||
/// While `Option<T>` will handle empty parameters (e.g. `param=`), beware when using this with a
|
||||
/// `Vec<T>`. If your list is optional, use `Vec<T>` in combination with `#[serde(default)]`
|
||||
/// instead of `Option<Vec<T>>`. `Option<Vec<T>>` will handle 0, 2, or more arguments, but not one
|
||||
/// argument.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use axum::{routing::get, Router};
|
||||
/// use axum_extra::extract::Query;
|
||||
/// use serde::Deserialize;
|
||||
///
|
||||
/// #[derive(Deserialize)]
|
||||
/// struct Params {
|
||||
/// #[serde(default)]
|
||||
/// items: Vec<usize>,
|
||||
/// }
|
||||
///
|
||||
/// // This will parse 0 occurrences of `items` as an empty `Vec`.
|
||||
/// async fn process_items(Query(params): Query<Params>) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// let app = Router::new().route("/process_items", get(process_items));
|
||||
/// # let _: Router = app;
|
||||
/// ```
|
||||
/// [changelog]: https://github.com/jplatte/serde_html_form/blob/main/CHANGELOG.md#030
|
||||
#[deprecated = "see documentation"]
|
||||
#[cfg_attr(docsrs, doc(cfg(feature = "query")))]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct Query<T>(pub T);
|
||||
@@ -140,6 +86,7 @@ composite_rejection! {
|
||||
/// Rejection used for [`Query`].
|
||||
///
|
||||
/// Contains one variant for each way the [`Query`] extractor can fail.
|
||||
#[deprecated = "because Query is deprecated"]
|
||||
pub enum QueryRejection {
|
||||
FailedToDeserializeQueryString,
|
||||
}
|
||||
@@ -147,7 +94,7 @@ composite_rejection! {
|
||||
|
||||
/// Extractor that deserializes query strings into `None` if no query parameters are present.
|
||||
///
|
||||
/// Otherwise behaviour is identical to [`Query`].
|
||||
/// Otherwise behaviour is identical to [`Query`][axum::extract::Query].
|
||||
/// `T` is expected to implement [`serde::Deserialize`].
|
||||
///
|
||||
/// # Example
|
||||
@@ -179,11 +126,6 @@ composite_rejection! {
|
||||
///
|
||||
/// If the query string cannot be parsed it will reject the request with a `400
|
||||
/// Bad Request` response.
|
||||
///
|
||||
/// For handling values being empty vs missing see the [query-params-with-empty-strings][example]
|
||||
/// example.
|
||||
///
|
||||
/// [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")))]
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct OptionalQuery<T>(pub Option<T>);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
//! `cookie-key-expansion` | Enables the [`Key::derive_from`](crate::extract::cookie::Key::derive_from) method |
|
||||
//! `erased-json` | Enables the [`ErasedJson`](crate::response::ErasedJson) response |
|
||||
//! `error-response` | Enables the [`InternalServerError`](crate::response::InternalServerError) response |
|
||||
//! `form` | Enables the [`Form`](crate::extract::Form) extractor |
|
||||
//! `form` (deprecated) | Enables the [`Form`](crate::extract::Form) extractor |
|
||||
//! `handler` | Enables the [handler] utilities |
|
||||
//! `json-deserializer` | Enables the [`JsonDeserializer`](crate::extract::JsonDeserializer) extractor |
|
||||
//! `json-lines` | Enables the [`JsonLines`](crate::extract::JsonLines) extractor and response |
|
||||
@@ -26,7 +26,7 @@
|
||||
//! `multipart` | Enables the [`Multipart`](crate::extract::Multipart) extractor |
|
||||
//! `optional-path` | Enables the [`OptionalPath`](crate::extract::OptionalPath) extractor |
|
||||
//! `protobuf` | Enables the [`Protobuf`](crate::protobuf::Protobuf) extractor and response |
|
||||
//! `query` | Enables the [`Query`](crate::extract::Query) extractor |
|
||||
//! `query` (deprecated) | Enables the [`Query`](crate::extract::Query) extractor |
|
||||
//! `routing` | Enables the [routing] utilities |
|
||||
//! `tracing` | Log rejections from built-in extractors | <span role="img" aria-label="Default feature">✔</span>
|
||||
//! `typed-routing` | Enables the [`TypedPath`](crate::routing::TypedPath) routing utilities and the `routing` feature. |
|
||||
|
||||
Reference in New Issue
Block a user