rocket/form/form.rs
1use std::ops::{Deref, DerefMut};
2
3use crate::Request;
4use crate::outcome::try_outcome;
5use crate::data::{Data, FromData, Outcome};
6use crate::http::{RawStr, ext::IntoOwned};
7use crate::form::prelude::{*, parser::{Parser, RawStrParser}};
8
9/// A data guard for [`FromForm`] types.
10///
11/// This type implements the [`FromData`] trait. It provides a generic means to
12/// parse arbitrary structures from incoming form data.
13///
14/// See the [forms guide](https://rocket.rs/master/guide/requests#forms) for
15/// general form support documentation.
16///
17/// # Leniency
18///
19/// A `Form<T>` will parse successfully from an incoming form if the form
20/// contains a superset of the fields in `T`. Said another way, a `Form<T>`
21/// automatically discards extra fields without error. For instance, if an
22/// incoming form contains the fields "a", "b", and "c" while `T` only contains
23/// "a" and "c", the form _will_ parse as `Form<T>`. To parse strictly, use the
24/// [`Strict`](crate::form::Strict) form guard.
25///
26/// # Usage
27///
28/// This type can be used with any type that implements the `FromForm` trait.
29/// The trait can be automatically derived; see the [`FromForm`] documentation
30/// for more information on deriving or implementing the trait.
31///
32/// Because `Form` implements `FromData`, it can be used directly as a target of
33/// the `data = "<param>"` route parameter as long as its generic type
34/// implements the `FromForm` trait:
35///
36/// ```rust
37/// # #[macro_use] extern crate rocket;
38/// use rocket::form::Form;
39/// use rocket::http::RawStr;
40///
41/// #[derive(FromForm)]
42/// struct UserInput<'r> {
43/// value: &'r str
44/// }
45///
46/// #[post("/submit", data = "<user_input>")]
47/// fn submit_task(user_input: Form<UserInput<'_>>) -> String {
48/// format!("Your value: {}", user_input.value)
49/// }
50/// ```
51///
52/// A type of `Form<T>` automatically dereferences into an `&T` or `&mut T`,
53/// though you can also transform a `Form<T>` into a `T` by calling
54/// [`into_inner()`](Form::into_inner()). Thanks to automatic dereferencing, you
55/// can access fields of `T` transparently through a `Form<T>`, as seen above
56/// with `user_input.value`.
57///
58/// ## Errors
59///
60/// A `Form<T>` data guard may fail, forward, or succeed.
61///
62/// If a request's content-type is neither [`ContentType::Form`] nor
63/// [`ContentType::FormData`], the guard **forwards**.
64///
65/// If the request `ContentType` _does_ identify as a form but the form data
66/// does not parse as `T`, according to `T`'s [`FromForm`] implementation, the
67/// guard **fails**. The `Error` variant contains a vector of the [`Errors`]
68/// emitted by `T`'s `FromForm` parser. If the error is not caught by a
69/// [`form::Result<T>`](Result) or `Option<Form<T>>` data guard, the status code
70/// is set to [`Errors::status()`], and the corresponding error catcher is
71/// called.
72///
73/// Otherwise the guard **succeeds**.
74///
75/// [`ContentType::Form`]: crate::http::ContentType::Form
76/// [`ContentType::FormData`]: crate::http::ContentType::FormData
77///
78/// ## Data Limits
79///
80/// The total amount of data accepted by the `Form` data guard is limited by the
81/// following limits:
82///
83/// | Limit Name | Default | Description |
84/// |-------------|---------|------------------------------------|
85/// | `form` | 32KiB | total limit for url-encoded forms |
86/// | `data-form` | 2MiB | total limit for multipart forms |
87/// | `*` | N/A | each field type has its own limits |
88///
89/// As noted above, each form field type (a form guard) typically imposes its
90/// own limits. For example, the `&str` form guard imposes a data limit of
91/// `string` when multipart data is streamed.
92///
93/// ### URL-Encoded Forms
94///
95/// The `form` limit specifies the data limit for an entire url-encoded form
96/// data. It defaults to 32KiB. URL-encoded form data is percent-decoded, stored
97/// in-memory, and parsed into [`ValueField`]s. If the incoming data exceeds
98/// this limit, the `Form` data guard fails without attempting to parse fields
99/// with a `413: Payload Too Large` error.
100///
101/// ### Multipart Forms
102///
103/// The `data-form` limit specifies the data limit for an entire multipart form
104/// data stream. It defaults to 2MiB. Multipart data is streamed, and form
105/// fields are processed into [`DataField`]s or [`ValueField`]s as they arrive.
106/// If the commutative data received while streaming exceeds the limit, parsing
107/// is aborted, an error is created and pushed via [`FromForm::push_error()`],
108/// and the form is finalized.
109///
110/// ### Individual Fields
111///
112/// Individual fields _may_ have data limits as well. The type of the field
113/// determines whether there is a data limit. For instance, the `&str` type
114/// imposes the `string` data limit. Consult the type's documentation or
115/// [`FromFormField`] for details.
116///
117/// ### Changing Limits
118///
119/// To change data limits, set the `limits.form` and/or `limits.data-form`
120/// configuration parameters. For instance, to increase the URL-encoded forms
121/// limit to 128KiB for all environments, you might add the following to your
122/// `Rocket.toml`:
123///
124/// ```toml
125/// [global.limits]
126/// form = 128KiB
127/// ```
128///
129/// See the [`Limits`](crate::data::Limits) and [`config`](crate::config) docs
130/// for more.
131#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
132pub struct Form<T>(T);
133
134impl<T> Form<T> {
135 /// Consumes `self` and returns the inner value.
136 ///
137 /// Note that since `Form` implements [`Deref`] and [`DerefMut`] with
138 /// target `T`, reading and writing an inner value can be accomplished
139 /// transparently.
140 ///
141 /// # Example
142 ///
143 /// ```rust
144 /// # #[macro_use] extern crate rocket;
145 /// use rocket::form::Form;
146 ///
147 /// #[derive(FromForm)]
148 /// struct MyForm {
149 /// field: String,
150 /// }
151 ///
152 /// #[post("/submit", data = "<form>")]
153 /// fn submit(form: Form<MyForm>) -> String {
154 /// // We can read or mutate a value transparently:
155 /// let field: &str = &form.field;
156 ///
157 /// // To gain ownership, however, use `into_inner()`:
158 /// form.into_inner().field
159 /// }
160 /// ```
161 pub fn into_inner(self) -> T {
162 self.0
163 }
164}
165
166impl<T> From<T> for Form<T> {
167 #[inline]
168 fn from(val: T) -> Form<T> {
169 Form(val)
170 }
171}
172
173impl<'r, T: FromForm<'r>> Form<T> {
174 /// Leniently parses a `T` from a **percent-decoded**
175 /// `x-www-form-urlencoded` form string. Specifically, this method
176 /// implements [§5.1 of the WHATWG URL Living Standard] with the exception
177 /// of steps 3.4 and 3.5, which are assumed to already be reflected in
178 /// `string`, and then parses the fields as `T`.
179 ///
180 /// [§5.1 of the WHATWG URL Living Standard]: https://url.spec.whatwg.org/#application/x-www-form-urlencoded
181 ///
182 /// # Example
183 ///
184 /// ```rust
185 /// use rocket::form::{Form, FromForm};
186 ///
187 /// #[derive(FromForm)]
188 /// struct Pet<'r> {
189 /// name: &'r str,
190 /// wags: bool,
191 /// }
192 ///
193 /// let string = "name=Benson Wagger!&wags=true";
194 /// let pet: Pet<'_> = Form::parse(string).unwrap();
195 /// assert_eq!(pet.name, "Benson Wagger!");
196 /// assert_eq!(pet.wags, true);
197 /// ```
198 #[inline]
199 pub fn parse(string: &'r str) -> Result<'r, T> {
200 // WHATWG URL Living Standard 5.1 steps 1, 2, 3.1 - 3.3.
201 Self::parse_iter(Form::values(string))
202 }
203
204 /// Leniently parses a `T` from the **percent-decoded** `fields`.
205 /// Specifically, this method implements [§5.1 of the WHATWG URL Living
206 /// Standard] with the exception of step 3.
207 ///
208 /// [§5.1 of the WHATWG URL Living Standard]: https://url.spec.whatwg.org/#application/x-www-form-urlencoded
209 ///
210 /// # Example
211 ///
212 /// ```rust
213 /// use rocket::form::{Form, FromForm, ValueField};
214 ///
215 /// #[derive(FromForm)]
216 /// struct Pet<'r> {
217 /// name: &'r str,
218 /// wags: bool,
219 /// }
220 ///
221 /// let fields = vec![
222 /// ValueField::parse("name=Bob, the cat. :)"),
223 /// ValueField::parse("wags=no"),
224 /// ];
225 ///
226 /// let pet: Pet<'_> = Form::parse_iter(fields).unwrap();
227 /// assert_eq!(pet.name, "Bob, the cat. :)");
228 /// assert_eq!(pet.wags, false);
229 /// ```
230 pub fn parse_iter<I>(fields: I) -> Result<'r, T>
231 where I: IntoIterator<Item = ValueField<'r>>
232 {
233 // WHATWG URL Living Standard 5.1 steps 1, 2, 3.1 - 3.3.
234 let mut ctxt = T::init(Options::Lenient);
235 fields.into_iter().for_each(|f| T::push_value(&mut ctxt, f));
236 T::finalize(ctxt)
237 }
238}
239
240impl<T: for<'a> FromForm<'a> + 'static> Form<T> {
241 /// Leniently parses a `T` from a raw, `x-www-form-urlencoded` form string.
242 /// Specifically, this method implements [§5.1 of the WHATWG URL Living
243 /// Standard]. Because percent-decoding might modify the input string, the
244 /// output type `T` must be `'static`.
245 ///
246 /// [§5.1 of the WHATWG URL Living Standard]:https://url.spec.whatwg.org/#application/x-www-form-urlencoded
247 ///
248 /// # Example
249 ///
250 /// ```rust
251 /// use rocket::http::RawStr;
252 /// use rocket::form::{Form, FromForm};
253 ///
254 /// #[derive(FromForm)]
255 /// struct Pet {
256 /// name: String,
257 /// wags: bool,
258 /// }
259 ///
260 /// let string = RawStr::new("name=Benson+Wagger%21&wags=true");
261 /// let pet: Pet = Form::parse_encoded(string).unwrap();
262 /// assert_eq!(pet.name, "Benson Wagger!");
263 /// assert_eq!(pet.wags, true);
264 /// ```
265 pub fn parse_encoded(string: &RawStr) -> Result<'static, T> {
266 let buffer = SharedStack::new();
267 let mut ctxt = T::init(Options::Lenient);
268 for field in RawStrParser::new(&buffer, string) {
269 T::push_value(&mut ctxt, field)
270 }
271
272 T::finalize(ctxt).map_err(|e| e.into_owned())
273 }
274}
275
276impl Form<()> {
277 /// Returns an iterator of fields parsed from a `x-www-form-urlencoded` form
278 /// string. Specifically, this method implements steps 1, 2, and 3.1 - 3.3
279 /// of [§5.1 of the WHATWG URL Living Standard]. Fields in the returned
280 /// iterator _are not_ percent-decoded.
281 ///
282 /// [§5.1 of the WHATWG URL Living Standard]:https://url.spec.whatwg.org/#application/x-www-form-urlencoded
283 ///
284 /// # Example
285 ///
286 /// ```rust
287 /// use rocket::form::{Form, ValueField};
288 ///
289 /// let string = "name=Bobby Brown&&&email=me@rocket.rs";
290 /// let mut values = Form::values(string);
291 /// assert_eq!(values.next().unwrap(), ValueField::parse("name=Bobby Brown"));
292 /// assert_eq!(values.next().unwrap(), ValueField::parse("email=me@rocket.rs"));
293 /// assert!(values.next().is_none());
294 /// ```
295 pub fn values(string: &str) -> impl Iterator<Item = ValueField<'_>> {
296 // WHATWG URL Living Standard 5.1 steps 1, 2, 3.1 - 3.3.
297 string.split('&')
298 .filter(|s| !s.is_empty())
299 .map(ValueField::parse)
300 }
301}
302
303impl<T> Deref for Form<T> {
304 type Target = T;
305
306 fn deref(&self) -> &Self::Target {
307 &self.0
308 }
309}
310
311impl<T> DerefMut for Form<T> {
312 fn deref_mut(&mut self) -> &mut Self::Target {
313 &mut self.0
314 }
315}
316
317#[crate::async_trait]
318impl<'r, T: FromForm<'r>> FromData<'r> for Form<T> {
319 type Error = Errors<'r>;
320
321 async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
322 use either::Either;
323
324 let mut parser = try_outcome!(Parser::new(req, data).await);
325 let mut context = T::init(Options::Lenient);
326 while let Some(field) = parser.next().await {
327 match field {
328 Ok(Either::Left(value)) => T::push_value(&mut context, value),
329 Ok(Either::Right(data)) => T::push_data(&mut context, data).await,
330 Err(e) => T::push_error(&mut context, e),
331 }
332 }
333
334 match T::finalize(context) {
335 Ok(value) => Outcome::Success(Form(value)),
336 Err(e) => Outcome::Error((e.status(), e)),
337 }
338 }
339}