1 // Copyright 2016 `multipart` Crate Developers
2 //
3 // Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4 // http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5 // http://opensource.org/licenses/MIT>, at your option. This file may not be
6 // copied, modified, or distributed except according to those terms.
7 //! The server-side abstraction for multipart requests. Enabled with the `server` feature.
8 //!
9 //! Use this when you are implementing an HTTP server and want to
10 //! to accept, parse, and serve HTTP `multipart/form-data` requests (file uploads).
11 //!
12 //! See the `Multipart` struct for more info.
13 
14 pub extern crate buf_redux;
15 extern crate httparse;
16 extern crate twoway;
17 
18 use std::borrow::Borrow;
19 use std::io::prelude::*;
20 use std::io;
21 
22 use self::boundary::BoundaryReader;
23 
24 use self::field::PrivReadEntry;
25 
26 pub use self::field::{FieldHeaders, MultipartField, MultipartData, ReadEntry, ReadEntryResult};
27 
28 use self::save::SaveBuilder;
29 
30 pub use self::save::{Entries, SaveResult, SavedField};
31 
32 macro_rules! try_opt (
33     ($expr:expr) => (
34         match $expr {
35             Some(val) => val,
36             None => return None,
37         }
38     );
39     ($expr:expr, $before_ret:expr) => (
40         match $expr {
41             Some(val) => val,
42             None => {
43                 $before_ret;
44                 return None;
45             }
46         }
47     )
48 );
49 
50 macro_rules! try_read_entry {
51     ($self_:expr; $try:expr) => (
52         match $try {
53             Ok(res) => res,
54             Err(err) => return ::server::ReadEntryResult::Error($self_, err),
55         }
56     )
57 }
58 
59 mod boundary;
60 mod field;
61 
62 #[cfg(feature = "hyper")]
63 pub mod hyper;
64 
65 #[cfg(feature = "iron")]
66 pub mod iron;
67 
68 #[cfg(feature = "tiny_http")]
69 pub mod tiny_http;
70 
71 #[cfg(feature = "nickel")]
72 pub mod nickel;
73 
74 pub mod save;
75 
76 /// The server-side implementation of `multipart/form-data` requests.
77 ///
78 /// Implements `Borrow<R>` to allow access to the request body, if desired.
79 pub struct Multipart<R> {
80     reader: BoundaryReader<R>,
81 }
82 
83 impl Multipart<()> {
84     /// If the given `HttpRequest` is a multipart/form-data POST request,
85     /// return the request body wrapped in the multipart reader. Otherwise,
86     /// returns the original request.
from_request<R: HttpRequest>(req: R) -> Result<Multipart<R::Body>, R>87     pub fn from_request<R: HttpRequest>(req: R) -> Result<Multipart<R::Body>, R> {
88         //FIXME: move `map` expr to `Some` arm when nonlexical borrow scopes land.
89         let boundary = match req.multipart_boundary().map(String::from) {
90             Some(boundary) => boundary,
91             None => return Err(req),
92         };
93 
94         Ok(Multipart::with_body(req.body(), boundary))
95     }
96 }
97 
98 impl<R: Read> Multipart<R> {
99     /// Construct a new `Multipart` with the given body reader and boundary.
100     ///
101     /// ## Note: `boundary`
102     /// This will prepend the requisite `--` to the boundary string as documented in
103     /// [IETF RFC 1341, Section 7.2.1: "Multipart: the common syntax"][rfc1341-7.2.1].
104     /// Simply pass the value of the `boundary` key from the `Content-Type` header in the
105     /// request (or use `Multipart::from_request()`, if supported).
106     ///
107     /// [rfc1341-7.2.1]: https://tools.ietf.org/html/rfc1341#page-30
with_body<Bnd: Into<String>>(body: R, boundary: Bnd) -> Self108     pub fn with_body<Bnd: Into<String>>(body: R, boundary: Bnd) -> Self {
109         let boundary = boundary.into();
110 
111         info!("Multipart::with_boundary(_, {:?})", boundary);
112 
113         Multipart {
114             reader: BoundaryReader::from_reader(body, boundary),
115         }
116     }
117 
118     /// Read the next entry from this multipart request, returning a struct with the field's name and
119     /// data. See `MultipartField` for more info.
120     ///
121     /// ## Warning: Risk of Data Loss
122     /// If the previously returned entry had contents of type `MultipartField::File`,
123     /// calling this again will discard any unread contents of that entry.
read_entry(&mut self) -> io::Result<Option<MultipartField<&mut Self>>>124     pub fn read_entry(&mut self) -> io::Result<Option<MultipartField<&mut Self>>> {
125         self.read_entry_mut().into_result()
126     }
127 
128     /// Read the next entry from this multipart request, returning a struct with the field's name and
129     /// data. See `MultipartField` for more info.
into_entry(self) -> ReadEntryResult<Self>130     pub fn into_entry(self) -> ReadEntryResult<Self> {
131         self.read_entry()
132     }
133 
134     /// Call `f` for each entry in the multipart request.
135     ///
136     /// This is a substitute for Rust not supporting streaming iterators (where the return value
137     /// from `next()` borrows the iterator for a bound lifetime).
138     ///
139     /// Returns `Ok(())` when all fields have been read, or the first error.
foreach_entry<F>(&mut self, mut foreach: F) -> io::Result<()> where F: FnMut(MultipartField<&mut Self>)140     pub fn foreach_entry<F>(&mut self, mut foreach: F) -> io::Result<()> where F: FnMut(MultipartField<&mut Self>) {
141         loop {
142             match self.read_entry() {
143                 Ok(Some(field)) => foreach(field),
144                 Ok(None) => return Ok(()),
145                 Err(err) => return Err(err),
146             }
147         }
148     }
149 
150     /// Get a builder type for saving the files in this request to the filesystem.
151     ///
152     /// See [`SaveBuilder`](save/struct.SaveBuilder.html) for more information.
save(&mut self) -> SaveBuilder<&mut Self>153     pub fn save(&mut self) -> SaveBuilder<&mut Self> {
154         SaveBuilder::new(self)
155     }
156 }
157 
158 impl<R> Borrow<R> for Multipart<R> {
borrow(&self) -> &R159     fn borrow(&self) -> &R {
160         self.reader.borrow()
161     }
162 }
163 
164 impl<R: Read> PrivReadEntry for Multipart<R> {
165     type Source = BoundaryReader<R>;
166 
source_mut(&mut self) -> &mut BoundaryReader<R>167     fn source_mut(&mut self) -> &mut BoundaryReader<R> {
168         &mut self.reader
169     }
170 
set_min_buf_size(&mut self, min_buf_size: usize)171     fn set_min_buf_size(&mut self, min_buf_size: usize) {
172         self.reader.set_min_buf_size(min_buf_size)
173     }
174 
175     /// Consume the next boundary.
176     /// Returns `true` if a field should follow this boundary, `false` otherwise.
consume_boundary(&mut self) -> io::Result<bool>177     fn consume_boundary(&mut self) -> io::Result<bool> {
178         debug!("Consume boundary!");
179         self.reader.consume_boundary()
180     }
181 }
182 
183 /// A server-side HTTP request that may or may not be multipart.
184 ///
185 /// May be implemented by mutable references if providing the request or body by-value is
186 /// undesirable.
187 pub trait HttpRequest {
188     /// The body of this request.
189     type Body: Read;
190     /// Get the boundary string of this request if it is a POST request
191     /// with the `Content-Type` header set to `multipart/form-data`.
192     ///
193     /// The boundary string should be supplied as an extra value of the `Content-Type` header, e.g.
194     /// `Content-Type: multipart/form-data; boundary={boundary}`.
multipart_boundary(&self) -> Option<&str>195     fn multipart_boundary(&self) -> Option<&str>;
196 
197     /// Return the request body for reading.
body(self) -> Self::Body198     fn body(self) -> Self::Body;
199 }
200 
201 #[test]
issue_104()202 fn issue_104() {
203     ::init_log();
204 
205     use std::io::Cursor;
206 
207     let body = "\
208     POST /test.html HTTP/1.1\r\n\
209     Host: example.org\r\n\
210     Content-Type: multipart/form-data;boundary=\"boundary\"\r\n\r\n\
211     Content-Disposition: form-data; name=\"field1\"\r\n\r\n\
212     value1\r\n\
213     Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\r\n\r\n\
214     value2 ";
215 
216     let request = Cursor::new(body);
217 
218     let mut multipart = Multipart::with_body(request, "boundary");
219     multipart.foreach_entry(|_field| {/* Do nothing */}).unwrap_err();
220 }
221 
222 #[test]
issue_114()223 fn issue_114() {
224     ::init_log();
225 
226     fn consume_all<R: BufRead>(mut rdr: R) {
227         loop {
228             let consume = rdr.fill_buf().unwrap().len();
229             if consume == 0 { return; }
230             rdr.consume(consume);
231         }
232     }
233 
234     use std::io::Cursor;
235 
236     let body = "\
237     --------------------------c616e5fded96a3c7\r\n\
238     Content-Disposition: form-data; name=\"key1\"\r\n\r\n\
239     v1,\r\n\
240     --------------------------c616e5fded96a3c7\r\n\
241     Content-Disposition: form-data; name=\"key2\"\r\n\r\n\
242     v2,\r\n\
243     --------------------------c616e5fded96a3c7\r\n\
244     Content-Disposition: form-data; name=\"key3\"\r\n\r\n\
245     v3\r\n\
246     --------------------------c616e5fded96a3c7--\r\n";
247 
248     let request = Cursor::new(body);
249     let mut multipart = Multipart::with_body(request, "------------------------c616e5fded96a3c7");
250 
251     // one error if you do nothing
252     multipart.foreach_entry(|_entry| { /* do nothing */}).unwrap();
253 
254     // a different error if you skip the first field
255     multipart.foreach_entry(|entry| if *entry.headers.name != *"key1" { consume_all(entry.data); })
256         .unwrap();
257 
258 
259     multipart.foreach_entry(|_entry| () /* match entry.headers.name.as_str() {
260         "file" => {
261             let mut vec = Vec::new();
262             entry.data.read_to_end(&mut vec).expect("can't read");
263             // message.file = String::from_utf8(vec).ok();
264             println!("key file got");
265         }
266 
267         "key1" => {
268             let mut vec = Vec::new();
269             entry.data.read_to_end(&mut vec).expect("can't read");
270             // message.key1 = String::from_utf8(vec).ok();
271             println!("key1 got");
272         }
273 
274         "key2" => {
275             let mut vec = Vec::new();
276             entry.data.read_to_end(&mut vec).expect("can't read");
277             // message.key2 = String::from_utf8(vec).ok();
278             println!("key2 got");
279         }
280 
281         _ => {
282             // as multipart has a bug https://github.com/abonander/multipart/issues/114
283             // we manually do read_to_end here
284             //let mut _vec = Vec::new();
285             //entry.data.read_to_end(&mut _vec).expect("can't read");
286             println!("key neglected");
287         }
288     }*/)
289     .expect("Unable to iterate multipart?")
290 }
291