multer/constraints.rs
1use crate::size_limit::SizeLimit;
2
3/// Represents some rules to be applied on the stream and field's content size
4/// to prevent DoS attacks.
5///
6/// It's recommended to add some rules on field (specially text field) size to
7/// avoid potential DoS attacks from attackers running the server out of memory.
8/// This type provides some API to apply constraints on very granular level to
9/// make `multipart/form-data` safe. By default, it does not apply any
10/// constraint.
11///
12/// # Examples
13///
14/// ```
15/// use multer::{Multipart, Constraints, SizeLimit};
16/// # use bytes::Bytes;
17/// # use std::convert::Infallible;
18/// # use futures_util::stream::once;
19///
20/// # async fn run() {
21/// # let data = "--X-BOUNDARY\r\nContent-Disposition: form-data; name=\"my_text_field\"\r\n\r\nabcd\r\n--X-BOUNDARY--\r\n";
22/// # let some_stream = once(async move { Result::<Bytes, Infallible>::Ok(Bytes::from(data)) });
23/// // Create some constraints to be applied to the fields to prevent DoS attack.
24/// let constraints = Constraints::new()
25/// // We only accept `my_text_field` and `my_file_field` fields,
26/// // For any unknown field, we will throw an error.
27/// .allowed_fields(vec!["my_text_field", "my_file_field"])
28/// .size_limit(
29/// SizeLimit::new()
30/// // Set 15mb as size limit for the whole stream body.
31/// .whole_stream(15 * 1024 * 1024)
32/// // Set 10mb as size limit for all fields.
33/// .per_field(10 * 1024 * 1024)
34/// // Set 30kb as size limit for our text field only.
35/// .for_field("my_text_field", 30 * 1024),
36/// );
37///
38/// // Create a `Multipart` instance from a stream and the constraints.
39/// let mut multipart = Multipart::with_constraints(some_stream, "X-BOUNDARY", constraints);
40///
41/// while let Some(field) = multipart.next_field().await.unwrap() {
42/// let content = field.text().await.unwrap();
43/// assert_eq!(content, "abcd");
44/// }
45/// # }
46/// # tokio::runtime::Runtime::new().unwrap().block_on(run());
47/// ```
48#[derive(Debug, Default)]
49pub struct Constraints {
50 pub(crate) size_limit: SizeLimit,
51 pub(crate) allowed_fields: Option<Vec<String>>,
52}
53
54impl Constraints {
55 /// Creates a set of rules with default behaviour.
56 pub fn new() -> Constraints {
57 Constraints::default()
58 }
59
60 /// Applies rules on field's content length.
61 pub fn size_limit(self, size_limit: SizeLimit) -> Constraints {
62 Constraints {
63 size_limit,
64 allowed_fields: self.allowed_fields,
65 }
66 }
67
68 /// Specify which fields should be allowed, for any unknown field, the
69 /// [`next_field`](crate::Multipart::next_field) will throw an error.
70 pub fn allowed_fields<N: Into<String>>(self, allowed_fields: Vec<N>) -> Constraints {
71 let allowed_fields = allowed_fields.into_iter().map(|item| item.into()).collect();
72
73 Constraints {
74 size_limit: self.size_limit,
75 allowed_fields: Some(allowed_fields),
76 }
77 }
78
79 pub(crate) fn is_it_allowed(&self, field: Option<&str>) -> bool {
80 if let Some(ref allowed_fields) = self.allowed_fields {
81 field
82 .map(|field| allowed_fields.iter().any(|item| item == field))
83 .unwrap_or(false)
84 } else {
85 true
86 }
87 }
88}