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