1- use super :: { has_content_type, rejection:: * , FromRequest , RequestParts } ;
21use crate :: body:: { Bytes , HttpBody } ;
2+ use crate :: extract:: { has_content_type, rejection:: * , FromRequest , RequestParts } ;
33use crate :: BoxError ;
44use async_trait:: async_trait;
5- use http:: Method ;
5+ use axum_core:: response:: { IntoResponse , Response } ;
6+ use http:: header:: CONTENT_TYPE ;
7+ use http:: { Method , StatusCode } ;
68use serde:: de:: DeserializeOwned ;
9+ use serde:: Serialize ;
710use std:: ops:: Deref ;
811
9- /// Extractor that deserializes `application/x-www-form-urlencoded` requests
10- /// into some type.
12+ /// URL encoded extractor and response.
1113///
12- /// `T` is expected to implement [`serde::Deserialize`].
14+ /// # As extractor
1315///
14- /// # Example
16+ /// If used as an extractor `Form` will deserialize `application/x-www-form-urlencoded` request
17+ /// bodies into some target type via [`serde::Deserialize`].
1518///
16- /// ```rust,no_run
17- /// use axum::{
18- /// extract::Form,
19- /// routing::post,
20- /// Router,
21- /// };
19+ /// ```rust
20+ /// use axum::Form;
2221/// use serde::Deserialize;
2322///
2423/// #[derive(Deserialize)]
@@ -27,19 +26,31 @@ use std::ops::Deref;
2726/// password: String,
2827/// }
2928///
30- /// async fn accept_form(form: Form<SignUp>) {
31- /// let sign_up: SignUp = form.0;
32- ///
29+ /// async fn accept_form(Form(sign_up): Form<SignUp>) {
3330/// // ...
3431/// }
32+ /// ```
33+ ///
34+ /// Note that `Content-Type: multipart/form-data` requests are not supported. Use [`Multipart`]
35+ /// instead.
36+ ///
37+ /// # As response
38+ ///
39+ /// ```rust
40+ /// use axum::Form;
41+ /// use serde::Serialize;
42+ ///
43+ /// #[derive(Serialize)]
44+ /// struct Payload {
45+ /// value: String,
46+ /// }
3547///
36- /// let app = Router::new().route("/sign_up", post(accept_form));
37- /// # async {
38- /// # axum::Server::bind(&"".parse().unwrap()).serve(app.into_make_service()).await.unwrap();
39- /// # };
48+ /// async fn handler() -> Form<Payload> {
49+ /// Form(Payload { value: "foo".to_owned() })
50+ /// }
4051/// ```
4152///
42- /// Note that `Content-Type: multipart/form-data` requests are not supported.
53+ /// [`Multipart`]: crate::extract::Multipart
4354#[ cfg_attr( docsrs, doc( cfg( feature = "form" ) ) ) ]
4455#[ derive( Debug , Clone , Copy , Default ) ]
4556pub struct Form < T > ( pub T ) ;
7485 }
7586}
7687
88+ impl < T > IntoResponse for Form < T >
89+ where
90+ T : Serialize ,
91+ {
92+ fn into_response ( self ) -> Response {
93+ match serde_urlencoded:: to_string ( & self . 0 ) {
94+ Ok ( body) => (
95+ [ ( CONTENT_TYPE , mime:: APPLICATION_WWW_FORM_URLENCODED . as_ref ( ) ) ] ,
96+ body,
97+ )
98+ . into_response ( ) ,
99+ Err ( err) => ( StatusCode :: INTERNAL_SERVER_ERROR , err. to_string ( ) ) . into_response ( ) ,
100+ }
101+ }
102+ }
103+
77104impl < T > Deref for Form < T > {
78105 type Target = T ;
79106
0 commit comments