Implement IntoResponse for Form (#1095)

This commit is contained in:
David Pedersen 2022-06-17 20:23:57 +02:00 committed by GitHub
parent 93251fa203
commit 2f64064650
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 62 additions and 26 deletions

View file

@ -9,9 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **added:** Support resolving host name via `Forwarded` header in `Host`
extractor ([#1078])
- **added:** Implement `IntoResponse` for `Form` ([#1095])
- **change:** axum's MSRV is now 1.56 ([#1098])
[#1078]: https://github.com/tokio-rs/axum/pull/1078
[#1095]: https://github.com/tokio-rs/axum/pull/1095
[#1098]: https://github.com/tokio-rs/axum/pull/1098
# 0.5.7 (08. June, 2022)

View file

@ -39,11 +39,8 @@ pub use crate::Json;
pub use crate::Extension;
#[cfg(feature = "form")]
mod form;
#[cfg(feature = "form")]
#[doc(inline)]
pub use self::form::Form;
#[doc(no_inline)]
pub use crate::form::Form;
#[cfg(feature = "matched-path")]
mod matched_path;

View file

@ -1,24 +1,23 @@
use super::{has_content_type, rejection::*, FromRequest, RequestParts};
use crate::body::{Bytes, HttpBody};
use crate::extract::{has_content_type, rejection::*, FromRequest, RequestParts};
use crate::BoxError;
use async_trait::async_trait;
use http::Method;
use axum_core::response::{IntoResponse, Response};
use http::header::CONTENT_TYPE;
use http::{Method, StatusCode};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::ops::Deref;
/// Extractor that deserializes `application/x-www-form-urlencoded` requests
/// into some type.
/// URL encoded extractor and response.
///
/// `T` is expected to implement [`serde::Deserialize`].
/// # As extractor
///
/// # Example
/// If used as an extractor `Form` will deserialize `application/x-www-form-urlencoded` request
/// bodies into some target type via [`serde::Deserialize`].
///
/// ```rust,no_run
/// use axum::{
/// extract::Form,
/// routing::post,
/// Router,
/// };
/// ```rust
/// use axum::Form;
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
@ -27,19 +26,31 @@ use std::ops::Deref;
/// password: String,
/// }
///
/// async fn accept_form(form: Form<SignUp>) {
/// let sign_up: SignUp = form.0;
///
/// async fn accept_form(Form(sign_up): Form<SignUp>) {
/// // ...
/// }
///
/// let app = Router::new().route("/sign_up", post(accept_form));
/// # async {
/// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
/// # };
/// ```
///
/// Note that `Content-Type: multipart/form-data` requests are not supported.
/// Note that `Content-Type: multipart/form-data` requests are not supported. Use [`Multipart`]
/// instead.
///
/// # As response
///
/// ```rust
/// use axum::Form;
/// use serde::Serialize;
///
/// #[derive(Serialize)]
/// struct Payload {
/// value: String,
/// }
///
/// async fn handler() -> Form<Payload> {
/// Form(Payload { value: "foo".to_owned() })
/// }
/// ```
///
/// [`Multipart`]: crate::extract::Multipart
#[cfg_attr(docsrs, doc(cfg(feature = "form")))]
#[derive(Debug, Clone, Copy, Default)]
pub struct Form<T>(pub T);
@ -74,6 +85,22 @@ where
}
}
impl<T> IntoResponse for Form<T>
where
T: Serialize,
{
fn into_response(self) -> Response {
match serde_urlencoded::to_string(&self.0) {
Ok(body) => (
[(CONTENT_TYPE, mime::APPLICATION_WWW_FORM_URLENCODED.as_ref())],
body,
)
.into_response(),
Err(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()).into_response(),
}
}
}
impl<T> Deref for Form<T> {
type Target = T;

View file

@ -395,6 +395,8 @@
pub(crate) mod macros;
mod extension;
#[cfg(feature = "form")]
mod form;
#[cfg(feature = "json")]
mod json;
#[cfg(feature = "headers")]
@ -434,5 +436,9 @@ pub use self::routing::Router;
#[cfg(feature = "headers")]
pub use self::typed_header::TypedHeader;
#[doc(inline)]
#[cfg(feature = "headers")]
pub use form::Form;
#[doc(inline)]
pub use axum_core::{BoxError, Error};

View file

@ -15,6 +15,10 @@ pub use crate::Json;
#[cfg(feature = "headers")]
pub use crate::TypedHeader;
#[cfg(feature = "form")]
#[doc(no_inline)]
pub use crate::form::Form;
#[doc(no_inline)]
pub use crate::Extension;