gnostr_web/parser/
mod.rs

1use std::collections::HashMap;
2
3pub mod body {
4    use crate::headers;
5    use crate::headers::Headers;
6    use crate::parser::body::reader::StreamReader;
7    use std::io::{Seek, SeekFrom, Write};
8    use tempfile::NamedTempFile;
9
10    pub struct Limits {
11        pub max_body_size: usize,
12    }
13
14    #[derive(Debug)]
15    pub enum BodyReadError {
16        MaxBodySizeExceed,
17        ContentLengthMissing,
18        BodyAlreadyRead,
19        Others(&'static str),
20    }
21
22    pub mod reader {
23        use crate::parser::body::{BodyReadError, Limits};
24        use std::io::Read;
25        use std::net::TcpStream;
26
27        pub trait StreamReader {
28            fn get_chunk(&mut self) -> Result<Vec<u8>, BodyReadError>;
29            fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, BodyReadError>;
30        }
31
32        pub struct BodyReader {
33            stream: TcpStream,
34            content_length: usize,
35            bytes_read: usize,
36            limits: Limits,
37        }
38
39        impl BodyReader {
40            pub fn new(
41                stream: TcpStream,
42                content_length: usize,
43                bytes_read: usize,
44                limits: Limits,
45            ) -> Self {
46                return Self {
47                    stream,
48                    content_length,
49                    bytes_read,
50                    limits,
51                };
52            }
53        }
54
55        impl StreamReader for BodyReader {
56            fn get_chunk(&mut self) -> Result<Vec<u8>, BodyReadError> {
57                if self.bytes_read >= self.content_length {
58                    return Err(BodyReadError::MaxBodySizeExceed);
59                }
60
61                if self.bytes_read >= self.limits.max_body_size {
62                    return Err(BodyReadError::BodyAlreadyRead);
63                }
64
65                let mut buffer = [0u8; 1024];
66                let read_result = self.stream.read(&mut buffer);
67                if !read_result.is_ok() {
68                    return Err(BodyReadError::Others(
69                        "Unable to read stream. May be client disconnected.",
70                    ));
71                }
72
73                let chunk_length = read_result.unwrap();
74                let chunk = Vec::from(&buffer[0..chunk_length]);
75                self.bytes_read += chunk_length;
76                return Ok(chunk);
77            }
78
79            fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, BodyReadError> {
80                if self.bytes_read >= self.content_length {
81                    return Err(BodyReadError::MaxBodySizeExceed);
82                }
83
84                if self.bytes_read >= self.limits.max_body_size {
85                    return Err(BodyReadError::BodyAlreadyRead);
86                }
87
88                let mut buffer = vec![0u8; size];
89                let read_result = self.stream.read_exact(&mut buffer);
90                if !read_result.is_ok() {
91                    return Err(BodyReadError::Others(
92                        "Unable to read stream. May be client disconnected.",
93                    ));
94                }
95                self.bytes_read += size;
96                return Ok(buffer);
97            }
98        }
99    }
100
101    pub fn parse<T: StreamReader>(
102        partial_bytes: Vec<u8>,
103        headers: &Headers,
104        mut reader: T,
105    ) -> Result<NamedTempFile, BodyReadError> {
106        let mut body_buffer = Vec::from(partial_bytes);
107        let mut body_read = body_buffer.len();
108
109        let content_length = headers::content_length(&headers);
110        if !content_length.is_some() {
111            return Err(BodyReadError::ContentLengthMissing);
112        }
113
114        // Create new tmp file
115        let temp_file_create = NamedTempFile::new();
116        let mut temp_file;
117
118        match temp_file_create {
119            Ok(file) => {
120                temp_file = file;
121            }
122
123            Err(_) => {
124                return Err(BodyReadError::Others("Error creating temporary file"));
125            }
126        }
127
128        let content_length = content_length.unwrap();
129
130        loop {
131            let write_result = temp_file.write_all(&body_buffer);
132            if !write_result.is_ok() {
133                return Err(BodyReadError::Others("Error writing to temporary file"));
134            }
135
136            if body_read >= content_length {
137                let seek_result = temp_file.seek(SeekFrom::Start(0));
138                if !seek_result.is_ok() {
139                    return Err(BodyReadError::Others("Failed to seek temporary file"));
140                }
141                return Ok(temp_file);
142            }
143
144            body_buffer.clear();
145
146            let read_result = reader.get_chunk();
147            match read_result {
148                Ok(chunk) => {
149                    body_read += chunk.len();
150                    body_buffer.extend(chunk);
151                }
152                Err(error) => {
153                    return Err(error);
154                }
155            }
156        }
157    }
158}
159
160pub fn parse_url_encoded(text: &str) -> HashMap<String, Vec<String>> {
161    let mut params = HashMap::new();
162    let values = text.split("&");
163
164    for value in values {
165        let key_values: Vec<&str> = value.split("=").collect();
166        if key_values.len() >= 2 {
167            let name = key_values.get(0).unwrap();
168            let value = key_values.get(1).unwrap();
169
170            let name_formatted = url_decode(name);
171            let value_formatted = url_decode(value);
172
173            if !params.contains_key(&name_formatted) {
174                params.insert(name.to_string(), Vec::new());
175            }
176
177            let values = params.get_mut(&name_formatted).unwrap();
178            values.push(value_formatted);
179        }
180    }
181    return params;
182}
183
184pub fn url_decode(value: &str) -> String {
185    return match urlencoding::decode(value) {
186        Ok(decoded_value) => decoded_value.to_string(),
187        Err(_) => value.to_string(),
188    };
189}
190
191pub mod url_encoded {
192    use crate::headers;
193    use crate::headers::Headers;
194    use crate::parser::parse_url_encoded;
195    use crate::parser::url_encoded::reader::StreamReader;
196    use std::collections::HashMap;
197
198    #[derive(Debug)]
199    pub enum UrlEncodedFormDataError {
200        /// Occurs, if the request body is not x-www-form-urlencoded
201        InvalidFormat(&'static str),
202        /// Occurs, if there is no Content-Length header
203        ContentLengthMissing(&'static str),
204        /// Occurs, if failed to parse the request
205        ParsingError(&'static str),
206        /// Occurs, if the request body size exceed the given size
207        MaxBodySizeExceed(&'static str),
208        /// Occurs, if parser requires more data to parse fully, but there is no more data left
209        BodyReadEnd,
210        /// Occurs, if error not fulfilled by above conditions
211        Others(&'static str),
212    }
213
214    pub mod reader {
215        use crate::parser::url_encoded::UrlEncodedFormDataError;
216        use std::io::Read;
217        use std::net::TcpStream;
218
219        /// The reusable trait for fetching "x-www-form-urlencoded" form data
220        pub trait StreamReader {
221            fn get_chunk(&mut self) -> Result<Vec<u8>, UrlEncodedFormDataError>;
222            fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, UrlEncodedFormDataError>;
223        }
224
225        pub struct UrlEncodedReader {
226            pub stream: TcpStream,
227            pub content_length: usize,
228            // Size of bytes that has been already read
229            pub bytes_read: usize,
230            pub body_ended: bool,
231        }
232
233        impl UrlEncodedReader {
234            pub fn new(stream: TcpStream, content_length: usize, bytes_read: usize) -> Self {
235                let body_ended;
236
237                if bytes_read == content_length {
238                    body_ended = true;
239                } else {
240                    body_ended = false;
241                };
242
243                return Self {
244                    stream,
245                    content_length,
246                    bytes_read,
247                    body_ended,
248                };
249            }
250
251            fn update_read_status(&mut self, new_chunk: &[u8]) {
252                self.bytes_read += new_chunk.len();
253
254                if self.bytes_read >= self.content_length {
255                    self.body_ended = true;
256                }
257            }
258        }
259
260        impl StreamReader for UrlEncodedReader {
261            fn get_chunk(&mut self) -> Result<Vec<u8>, UrlEncodedFormDataError> {
262                if self.body_ended {
263                    return Err(UrlEncodedFormDataError::BodyReadEnd);
264                }
265
266                let mut buffer = [0u8; 1024];
267                let read_result = self.stream.read(&mut buffer);
268
269                if !read_result.is_ok() {
270                    return Err(UrlEncodedFormDataError::Others(
271                        "Unable to read stream. May be client disconnected.",
272                    ));
273                }
274
275                let read_size = read_result.unwrap();
276
277                if read_size == 0 {
278                    return Err(UrlEncodedFormDataError::Others(
279                        "Bytes read size is 0. Probably client disconnected.",
280                    ));
281                }
282
283                let chunk = &buffer[0..read_size];
284                self.update_read_status(chunk);
285                return Ok(chunk.to_vec());
286            }
287
288            fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, UrlEncodedFormDataError> {
289                if self.body_ended {
290                    return Err(UrlEncodedFormDataError::BodyReadEnd);
291                }
292
293                let mut buffer = vec![0u8; size];
294                let result = self.stream.read_exact(&mut buffer);
295                if !result.is_ok() {
296                    return Err(UrlEncodedFormDataError::Others(
297                        "Unable to read stream. May be client disconnected.",
298                    ));
299                }
300
301                return Ok(buffer.to_vec());
302            }
303        }
304    }
305
306    pub struct Limits {
307        pub max_body_size: usize,
308    }
309
310    pub type FormFields = HashMap<String, Vec<String>>;
311
312    pub fn parse<T: StreamReader>(
313        partial_bytes: Vec<u8>,
314        headers: &Headers,
315        reader: &mut T,
316        limits: Limits,
317    ) -> Result<FormFields, UrlEncodedFormDataError> {
318        let mut body_buffer = Vec::from(partial_bytes);
319        let content_length = headers::content_length(headers);
320
321        if let Some(content_length) = content_length {
322            if content_length > limits.max_body_size {
323                return Err(UrlEncodedFormDataError::MaxBodySizeExceed(
324                    "Request body size is larger than the limit.",
325                ));
326            }
327        } else {
328            return Err(UrlEncodedFormDataError::ContentLengthMissing(
329                "Content-Length header is missing.",
330            ));
331        }
332
333        let content_length = content_length.unwrap();
334        let bytes_read = body_buffer.len();
335
336        // Load all the request body to memory
337        while content_length > bytes_read {
338            let request_chunk = reader.get_chunk();
339
340            match request_chunk {
341                Ok(chunk) => {
342                    body_buffer.extend(chunk);
343                }
344
345                Err(error) => {
346                    return Err(error);
347                }
348            }
349        }
350
351        let value = String::from_utf8_lossy(&body_buffer).to_string();
352        let form_values = parse_url_encoded(value.as_str());
353        return Ok(form_values);
354    }
355}
356
357pub mod multipart {
358    use crate::headers;
359    use crate::headers::Headers;
360    use regex::Regex;
361    use std::collections::HashMap;
362    use std::io::{Seek, SeekFrom, Write};
363    use tempfile::NamedTempFile;
364
365    #[derive(Debug)]
366    pub enum MultipartFormDataError {
367        /// Occurs, if the request body is not multipart/form-data
368        InvalidMultiPart(&'static str),
369        /// Occurs, if failed to parse the request
370        ParsingError(&'static str),
371        /// Occurs, if the size of the form part header exceeds the given size
372        HeaderSizeExceed(&'static str),
373        /// Occurs, if the request body size exceed the given size
374        MaxBodySizeExceed(&'static str),
375        /// Occurs, if the form part content size exceed
376        MaxFieldSizeExceed(String, &'static str),
377        /// Occurs, if parser requires more data to parse fully, but there is no more data left
378        BodyReadEnd,
379        /// Occurs, if error not fulfilled by above conditions
380        Others(&'static str),
381    }
382
383    /// The reusable trait for fetching multipart bytes
384    pub trait StreamReader {
385        fn get_chunk(&mut self) -> Result<Vec<u8>, MultipartFormDataError>;
386        fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, MultipartFormDataError>;
387    }
388
389    /// Extracts boundary from Content-Type header.
390    pub fn extract_boundary(content_type: &String) -> Option<String> {
391        let value: Vec<&str> = content_type.split(";").collect();
392
393        if value.len() >= 2 {
394            let content_type_text = value.get(1).unwrap().trim();
395            let boundary = content_type_text.strip_prefix("boundary=").unwrap();
396            return Some(boundary.to_string());
397        }
398
399        return None;
400    }
401
402    pub mod reader {
403        use crate::parser::multipart::{MultipartFormDataError, StreamReader};
404        use std::io::Read;
405        use std::net::TcpStream;
406
407        pub struct FormDataReader {
408            pub stream: TcpStream,
409            pub boundary_end_bytes: Vec<u8>,
410            pub content_length: Option<usize>,
411            // Size of bytes that has been already read
412            pub bytes_read: usize,
413            pub body_ended: bool,
414            /// Store only some amount of bytes equals to the boundary end bytes
415            body_buffer: Vec<u8>,
416        }
417
418        impl FormDataReader {
419            pub fn new(
420                stream: TcpStream,
421                boundary: String,
422                content_length: Option<usize>,
423                body_read: usize,
424            ) -> Self {
425                let boundary_end = format!("--{}\r\n", boundary);
426                let boundary_end_bytes = boundary_end.as_bytes().to_vec();
427                let body_buffer = Vec::with_capacity(boundary_end_bytes.len());
428
429                let body_ended;
430                if let Some(content_length) = content_length {
431                    body_ended = body_read >= content_length;
432                } else if body_buffer.ends_with(&boundary_end_bytes) {
433                    body_ended = true;
434                } else {
435                    body_ended = false;
436                }
437
438                return Self {
439                    stream,
440                    boundary_end_bytes,
441                    content_length,
442                    bytes_read: body_read,
443                    body_ended,
444                    body_buffer,
445                };
446            }
447
448            /// Performs checks and updates status
449            fn update_read_status(&mut self, new_chunk: &[u8]) {
450                self.bytes_read += new_chunk.len();
451
452                if self.content_length.is_some() {
453                    let body_ended = self.bytes_read >= self.content_length.unwrap();
454                    if body_ended {
455                        self.body_ended = true;
456                    }
457                } else {
458                    if self.body_buffer.ends_with(&self.boundary_end_bytes) {
459                        self.body_ended = true;
460                        return;
461                    }
462
463                    // Read is not finished yet, but we will prepare for next time
464                    // If length of new chunk is more than the boundary end bytes, it means data is not ended yet.
465                    // We can copy whole last bytes equivalent of boundary end bytes
466                    if new_chunk.len() > self.boundary_end_bytes.len() {
467                        self.body_buffer.clear();
468                        let last_sice = &new_chunk[(self.boundary_end_bytes.len()
469                            - self.boundary_end_bytes.len())
470                            ..self.boundary_end_bytes.len()];
471                        self.body_buffer.extend(last_sice);
472                    } else {
473                        // If the chunk is smaller than the boundary length
474                        // Merge old and new slice and save in the body_buffer
475                        let start_index = self.boundary_end_bytes.len() - new_chunk.len() - 1;
476                        let old_slice_to_copy = &self.body_buffer[start_index..].to_owned();
477
478                        self.body_buffer.clear();
479                        self.body_buffer.extend(old_slice_to_copy);
480                        self.body_buffer.extend(new_chunk);
481                    }
482                }
483            }
484        }
485
486        impl StreamReader for FormDataReader {
487            fn get_chunk(&mut self) -> Result<Vec<u8>, MultipartFormDataError> {
488                if self.body_ended {
489                    return Err(MultipartFormDataError::BodyReadEnd);
490                }
491
492                const BUFFER_SIZE: usize = 8 * 1024; // 8 KiB
493                let mut buffer = [0u8; BUFFER_SIZE];
494                let result = self.stream.read(&mut buffer);
495
496                if !result.is_ok() {
497                    return Err(MultipartFormDataError::Others(
498                        "Unable to read stream. May be client disconnected.",
499                    ));
500                }
501
502                let read_size = result.unwrap();
503                if read_size == 0 {
504                    return Err(MultipartFormDataError::Others(
505                        "Bytes read size is 0. Probably client disconnected.",
506                    ));
507                }
508
509                let chunk_slice = &buffer[0..read_size];
510                self.update_read_status(&chunk_slice);
511
512                let chunk = Vec::from(chunk_slice);
513                return Ok(chunk);
514            }
515
516            fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, MultipartFormDataError> {
517                if self.body_ended {
518                    return Err(MultipartFormDataError::BodyReadEnd);
519                }
520
521                let mut buffer: Vec<u8> = vec![0u8; size];
522                let result = self.stream.read_exact(&mut buffer);
523                if !result.is_ok() {
524                    return Err(MultipartFormDataError::Others(
525                        "Unable to read stream. May be client disconnected.",
526                    ));
527                }
528
529                self.update_read_status(&buffer);
530                return Ok(buffer);
531            }
532        }
533    }
534
535    #[derive(Debug)]
536    pub struct FormPart {
537        pub name: Option<String>,
538        pub filename: Option<String>,
539        pub content_type: Option<String>,
540        pub temp_file: Option<NamedTempFile>,
541        pub value: Option<Vec<u8>>,
542    }
543
544    #[derive(Debug)]
545    pub struct FormPartLimit {
546        pub max_size: Option<usize>,
547        pub content_type: Option<String>,
548    }
549
550    #[derive(Debug)]
551    pub struct Limits {
552        pub max_body_size: Option<usize>,
553        pub max_header_size: Option<usize>,
554        pub max_value_size: Option<usize>,
555        pub form_part_limits: HashMap<String, FormPartLimit>,
556    }
557
558    impl Limits {
559        pub fn none() -> Self {
560            return Self {
561                max_body_size: None,
562                max_header_size: None,
563                max_value_size: None,
564                form_part_limits: HashMap::new(),
565            };
566        }
567    }
568
569    #[derive(Debug)]
570    pub enum FormPartResult {
571        CheckNext,
572        BodyCompleted,
573    }
574
575    impl FormPart {
576        pub fn empty() -> Self {
577            return FormPart {
578                name: None,
579                filename: None,
580                content_type: None,
581                temp_file: None,
582                value: None,
583            };
584        }
585    }
586
587    /// It expects that the header has been completely read including \r\n\r\n characters.
588    ///
589    ///
590    /// Here's example:
591    /// ```markdown
592    /// ----------------------------648887867674240986891965
593    /// Content-Disposition: form-data; name="name"
594    ///
595    /// John Doe
596    /// ----------------------------648887867674240986891965
597    /// Content-Disposition: form-data; name="file"; filename="a.txt"
598    /// Content-Type: text/plain
599    ///
600    ///
601    /// hello
602    ///
603    /// ----------------------------648887867674240986891965
604    /// Content-Disposition: form-data; name="gender"
605    ///
606    /// male
607    /// ----------------------------648887867674240986891965--
608    /// ```
609    pub fn parse<T: StreamReader>(
610        partial_bytes: Vec<u8>,
611        headers: &Headers,
612        reader: T,
613        limits: Limits,
614    ) -> Result<Vec<FormPart>, MultipartFormDataError> {
615        let content_type_bytes = headers.get("Content-Type");
616
617        let content_type: String;
618        if let Some(content_type_bytes) = content_type_bytes {
619            content_type = content_type_bytes.get(0).unwrap().to_owned();
620        } else {
621            return Err(MultipartFormDataError::InvalidMultiPart(
622                "Content-Type header missing.",
623            ));
624        };
625
626        let multipart_boundary: String;
627        if let Some(boundary) = extract_boundary(&content_type) {
628            multipart_boundary = boundary;
629        } else {
630            return Err(MultipartFormDataError::InvalidMultiPart(
631                "Unable to extract multipart boundary.",
632            ));
633        }
634
635        // Check if the client body is larger than the limit
636        if let Some(max_body_size) = limits.max_body_size {
637            if let Some(content_length) = headers::content_length(&headers) {
638                if content_length > max_body_size {
639                    return Err(MultipartFormDataError::MaxBodySizeExceed(
640                        "Maximum specified body size exceed.",
641                    ));
642                }
643            }
644        }
645
646        let body_buffer = Vec::from(partial_bytes);
647        return parse_body_parts(reader, body_buffer, &multipart_boundary, limits);
648    }
649
650    pub fn parse_body_parts<T: StreamReader>(
651        mut reader: T,
652        mut body_buffer: Vec<u8>,
653        boundary: &String,
654        limits: Limits,
655    ) -> Result<Vec<FormPart>, MultipartFormDataError> {
656        let mut form_parts = Vec::new();
657
658        // Remove starting boundary first. It will make parsing easy by matching \r\n--{boundary}
659
660        let start_boundary = format!("--{}\r\n", boundary);
661        let start_boundary_bytes = start_boundary.as_bytes();
662
663        // All the data is not be received. If not received try to read the required number bytes to make the boundary string.
664        if body_buffer.len() <= start_boundary_bytes.len() {
665            // Instead of reading bytes of some length, we will read exactly bytes required to prevent from reading again.
666            let bytes_required = start_boundary_bytes.len() - body_buffer.len();
667            let chunk_request_result = reader.get_exact(bytes_required);
668
669            match chunk_request_result {
670                Ok(chunk) => {
671                    body_buffer.extend(chunk);
672                }
673
674                Err(error) => {
675                    return Err(error);
676                }
677            }
678        };
679
680        if !body_buffer_starts_with_boundary(&body_buffer, start_boundary_bytes) {
681            return Err(MultipartFormDataError::InvalidMultiPart(
682                "Body does not start with boundary",
683            ));
684        }
685
686        // Remove boundary header start
687        body_buffer = Vec::from(&body_buffer[start_boundary_bytes.len()..]);
688
689        // Now, we can start looping the form part contents.
690        loop {
691            // Extract header from form part
692            let header_result = extract_form_part_header(&mut reader, &mut body_buffer, &limits);
693            if !header_result.is_ok() {
694                return Err(header_result.unwrap_err());
695            }
696
697            let form_part_header = header_result.unwrap();
698            let header_text = String::from_utf8_lossy(&form_part_header).to_string();
699
700            // Parse header obtained above
701            let header_parse_result = parse_form_part_header(header_text);
702            if !header_parse_result.is_ok() {
703                return Err(header_parse_result.unwrap_err());
704            }
705
706            // Obtain form part after parsing header.
707            // This contains file metadata and form name, value
708            let mut form_part = header_parse_result.unwrap();
709
710            // Extract the body to value or temporary file.
711            // If it is file, it will be available on form_part.temp_file else value
712            let body_parse_result = extract_form_part_body(
713                &mut reader,
714                &mut body_buffer,
715                boundary,
716                &mut form_part,
717                &limits,
718            );
719
720            match body_parse_result {
721                Ok(result) => {
722                    match result {
723                        FormPartResult::BodyCompleted => {
724                            form_parts.push(form_part);
725                            return Ok(form_parts);
726                        }
727
728                        FormPartResult::CheckNext => {
729                            form_parts.push(form_part);
730                            // Continue looping
731                        }
732                    }
733                }
734
735                Err(error) => {
736                    return Err(error);
737                }
738            }
739        }
740    }
741
742    pub fn body_buffer_starts_with_boundary(
743        body_buffer: &Vec<u8>,
744        start_boundary_bytes: &[u8],
745    ) -> bool {
746        // Check if the body buffer starts with start boundary or not. If not we will discard and don't process further.
747        let extracted_boundary_slice = &body_buffer[0..start_boundary_bytes.len()];
748        return extracted_boundary_slice == start_boundary_bytes;
749    }
750
751    /// Parses the form part header and removes the header from body buffer including \r\n\r\n bytes.
752    ///
753    /// ```markdown
754    /// Content-Disposition: form-data; name="name"
755    ///
756
757    /// John Doe
758    /// ----------------------------648887867674240986891965
759    /// Content-Disposition: form-data; name="file"; filename="a.txt"
760    /// Content-Type: text/plain
761    ///
762    ///
763    /// ... continues
764    /// ```
765    pub fn extract_form_part_header<T: StreamReader>(
766        reader: &mut T,
767        body_buffer: &mut Vec<u8>,
768        limits: &Limits,
769    ) -> Result<Vec<u8>, MultipartFormDataError> {
770        // There can be one CRLF line break as well as two. Need to handle both cases.
771        let header_end_bytes = b"\r\n\r\n";
772        let mut form_part_header_buffer = Vec::new();
773
774        let max_header_size = limits.max_header_size;
775
776        loop {
777            let scan_result = body_buffer
778                .windows(header_end_bytes.len())
779                .position(|window| window == header_end_bytes);
780
781            if let Some(found_index) = scan_result {
782                // Copy the found header to form part header
783                form_part_header_buffer.extend(&body_buffer[0..found_index]);
784
785                // If MAX_HEADER_SIZE exceeds, return error.
786                if max_header_size.is_some()
787                    && (form_part_header_buffer.len() >= max_header_size.unwrap())
788                {
789                    return Err(MultipartFormDataError::HeaderSizeExceed(
790                        "Header size exceed max specified size",
791                    ));
792                }
793
794                // Remove the found header including trailing header end bytes
795                *body_buffer = Vec::from(&body_buffer[found_index + header_end_bytes.len()..]);
796                return Ok(form_part_header_buffer);
797            } else {
798                // Header is not found yet. However, we copy the unmatched buffer too except last 4 bytes;
799                // Last 4 bytes not copied to header buffer because it's half part may be available in the buffer next time
800                // after new read. So we can't check if it ends or not.
801                // If there is no enough data to copy to header buffer we ignore and fill more data to body buffer.
802                let to_copy_to_header_buffer =
803                    body_buffer.len() as i32 - header_end_bytes.len() as i32;
804                if to_copy_to_header_buffer > 0 {
805                    // Append new data to header buffer
806                    form_part_header_buffer.extend(header_end_bytes);
807                    // Also remove copied data from body buffer
808                    *body_buffer = Vec::from(&body_buffer[to_copy_to_header_buffer as usize..]);
809                }
810
811                // If MAX_HEADER_SIZE exceeds, return error.
812                if max_header_size.is_some()
813                    && (form_part_header_buffer.len() >= max_header_size.unwrap())
814                {
815                    return Err(MultipartFormDataError::HeaderSizeExceed(
816                        "Header size exceed max specified size",
817                    ));
818                } else {
819                    let request_new_chunk = reader.get_chunk();
820
821                    match request_new_chunk {
822                        Ok(new_chunk) => {
823                            body_buffer.extend(new_chunk);
824                        }
825
826                        Err(error) => {
827                            return Err(error);
828                        }
829                    }
830                }
831            };
832        }
833    }
834
835    /// Expects only the header
836    pub fn parse_form_part_header(part_header: String) -> Result<FormPart, MultipartFormDataError> {
837        let mut form_part = FormPart::empty();
838
839        let headers: Vec<&str> = part_header.split("\r\n").collect();
840
841        // Splitting headers lines by \r\n
842        for header_line in headers {
843            // Parse individual header line and update the form part.
844            parse_header_line(header_line, &mut form_part);
845        }
846
847        return Ok(form_part);
848    }
849
850    pub fn parse_header_line(line: &str, form_part: &mut FormPart) {
851        let line = line.trim();
852
853        if line.is_empty() {
854            return;
855        }
856
857        let name_value: Vec<&str> = line.split(":").collect();
858        if name_value.len() >= 2 {
859            let header_name = name_value.get(0).unwrap().trim();
860            let header_value = name_value.get(1).unwrap().trim();
861
862            // If the header is Content-Disposition, extract the metadata
863            if header_name.to_lowercase() == "Content-Disposition".to_lowercase() {
864                parse_content_disposition_value(header_value, form_part);
865            } else if header_name.to_lowercase() == "Content-Type".to_lowercase() {
866                parse_content_type(header_value, form_part);
867            }
868        }
869    }
870
871    /// Expects value of Content-Disposition value.
872    ///
873    /// Example:
874    /// ```markdown
875    /// form-data; name="username"
876    /// form-data; name="file"; filename="hello.txt"
877    /// ```
878    pub fn parse_content_disposition_value(value: &str, form_part: &mut FormPart) {
879        let value = value.trim();
880
881        if !value.starts_with("form-data;") {
882            // Not a valid Content-Deposition value for form part header
883            return;
884        }
885
886        let remaining = value.strip_prefix("form-data;").unwrap().trim();
887        let pattern = Regex::new(r#"(?<attribute>\w+)="(?<value>[^"]*)""#).unwrap();
888
889        for captured in pattern.captures_iter(remaining) {
890            let attribute = &captured["attribute"];
891            let value = &captured["value"];
892
893            if attribute == "name" {
894                form_part.name = Some(value.to_string());
895            } else if attribute == "filename" {
896                form_part.filename = Some(value.to_string());
897            }
898        }
899    }
900
901    pub fn parse_content_type(value: &str, form_part: &mut FormPart) {
902        form_part.content_type = Some(value.to_string());
903    }
904
905    pub fn extract_form_part_body<T: StreamReader>(
906        reader: &mut T,
907        body_buffer: &mut Vec<u8>,
908        boundary: &String,
909        form_part: &mut FormPart,
910        limits: &Limits,
911    ) -> Result<FormPartResult, MultipartFormDataError> {
912        let field_name = &form_part.name;
913
914        let mut form_part_limit: Option<&FormPartLimit> = None;
915        if field_name.is_some() {
916            let field_name = field_name.clone().unwrap();
917            form_part_limit = limits.form_part_limits.get(&field_name);
918        }
919
920        let is_file = form_part.filename.is_some();
921        if is_file {
922            return extract_form_file_body(
923                reader,
924                body_buffer,
925                boundary,
926                form_part,
927                form_part_limit,
928            );
929        }
930
931        let field_value_limit;
932        if form_part_limit.is_some() {
933            // No limit set for field value. Since it will be stored in the memory,
934            // default limit is set
935            field_value_limit = FormPartLimit {
936                max_size: form_part_limit.unwrap().max_size,
937                content_type: None,
938            };
939        } else {
940            field_value_limit = FormPartLimit {
941                max_size: limits.max_value_size,
942                content_type: None,
943            }
944        }
945
946        form_part_limit = Some(&field_value_limit);
947        return extract_form_value(reader, body_buffer, boundary, form_part, form_part_limit);
948    }
949
950    /// It writes the file to temporary file.
951    /// Example to copy file
952    /// ```markdown
953    /// // Example to copy temp file
954    ///
955    /// let filename = &form_part.filename.unwrap();
956    /// let owned = filename.to_owned();
957    /// let path = temp_file.path();
958    ///
959    /// fs::copy(path, owned).expect("Error copying");
960    /// ```
961    pub fn extract_form_file_body<T: StreamReader>(
962        reader: &mut T,
963        body_buffer: &mut Vec<u8>,
964        boundary: &String,
965        form_part: &mut FormPart,
966        form_part_limit: Option<&FormPartLimit>,
967    ) -> Result<FormPartResult, MultipartFormDataError> {
968        // Create new tmp directory
969        let temp_file_create = NamedTempFile::new();
970        let mut temp_file;
971
972        match temp_file_create {
973            Ok(file) => {
974                temp_file = file;
975            }
976
977            Err(_) => {
978                return Err(MultipartFormDataError::Others(
979                    "Error creating temporary file",
980                ));
981            }
982        }
983
984        // Files can be ended with single CRLF line breaks as well as multiple.
985        // \r\n and --\r\n are ignored to match later. These will decide whether there is next form part or body ends.
986        let file_end_matcher = format!("\r\n--{}", boundary);
987        let file_end_matching_bytes = file_end_matcher.as_bytes();
988
989        let mut bytes_written: usize = 0;
990
991        loop {
992            let search_file_end = body_buffer
993                .windows(file_end_matching_bytes.len())
994                .position(|window| window == file_end_matching_bytes);
995
996            // Position where file_end_matcher started matching
997            if let Some(body_end_index) = search_file_end {
998                // Check if file is empty or not. If body_end_index is 0, either file is empty or file is already
999                // written but body end is just matched.
1000
1001                if body_end_index > 0 {
1002                    // Body end position has been found
1003                    // Exact body bytes left range
1004                    let mut bytes_to_copy = &body_buffer[0..body_end_index];
1005                    bytes_written += bytes_to_copy.len();
1006
1007                    // Check extra two bytes if the file body ends with \r\n. Some client adds double CRLF line breaks.
1008                    // If file body ends with \r\n, ignore
1009                    if bytes_to_copy.ends_with(b"\r\n") {
1010                        bytes_to_copy = &bytes_to_copy[0..bytes_to_copy.len() - 2];
1011                    }
1012
1013                    let write_result = temp_file.write_all(bytes_to_copy);
1014                    if !write_result.is_ok() {
1015                        return Err(MultipartFormDataError::Others(
1016                            "Error writing to temporary file",
1017                        ));
1018                    }
1019
1020                    // Remove copied data from body buffer including boundary by creating new array.
1021                    *body_buffer =
1022                        Vec::from(&body_buffer[body_end_index + file_end_matching_bytes.len()..]);
1023                }
1024
1025                // Check if the file size is more than the limit set.
1026                if form_part_limit.is_some()
1027                    && (bytes_written > form_part_limit.unwrap().max_size.unwrap())
1028                {
1029                    return Err(MultipartFormDataError::MaxFieldSizeExceed(
1030                        form_part.name.clone().unwrap().to_string(),
1031                        "The file is bigger than the maximum allowed size",
1032                    ));
1033                }
1034
1035                // Check if it is the last form content or still there are others.
1036                // If it is the last form part content, it will contain --\r\n in next bytes.
1037                // If it is not last the last form part content, there will be \r\n in next bytes.
1038                // Till now, we don't know if body is completed or not.
1039
1040                let end_body_bytes = b"--\r\n";
1041                let next_part_bytes = b"\r\n";
1042                // Read exact 4 bytes if there is nothing in the body buffer else request required number of bytes.
1043                // 4 bytes should be there before completing request body.
1044
1045                if body_buffer.len() < 4 {
1046                    // Amount of bytes to read
1047                    let bytes_to_read = 4 - body_buffer.len();
1048
1049                    let request_new_chunk = reader.get_exact(bytes_to_read);
1050                    match request_new_chunk {
1051                        Ok(chunk) => {
1052                            body_buffer.extend(chunk);
1053                        }
1054                        Err(error) => {
1055                            return Err(error);
1056                        }
1057                    }
1058                }
1059
1060                // Compare --\r\n
1061                let body_end_compare = &body_buffer[0..4];
1062                if body_end_compare == end_body_bytes {
1063                    // All form part has been parsed
1064                    body_buffer.clear();
1065                    if !temp_file.seek(SeekFrom::Start(0)).is_ok() {
1066                        return Err(MultipartFormDataError::Others(
1067                            "Error to seek start 0 temporary file.",
1068                        ));
1069                    }
1070
1071                    form_part.temp_file = Some(temp_file);
1072                    return Ok(FormPartResult::BodyCompleted);
1073                }
1074
1075                // Compare \r\n
1076                let form_part_next_compare = &body_buffer[0..2];
1077                if form_part_next_compare == next_part_bytes {
1078                    // Remove \r\n bytes from the body buffer
1079                    *body_buffer = Vec::from(&body_buffer[2..]);
1080
1081                    if !temp_file.seek(SeekFrom::Start(0)).is_ok() {
1082                        return Err(MultipartFormDataError::Others(
1083                            "Error seek to start 0 temporary file.",
1084                        ));
1085                    }
1086
1087                    form_part.temp_file = Some(temp_file);
1088                    return Ok(FormPartResult::CheckNext);
1089                }
1090
1091                // None of the condition is satisfied. Problem with the request body.
1092                return Err(MultipartFormDataError::ParsingError(
1093                    "Form content did not end with \r\n",
1094                ));
1095            } else {
1096                // Body end still not found. Add new chunk to body buffer
1097                // However we still write the data from the buffer except last bytes equal to the boundary match header.
1098                // We don't want to compare with half bytes of boundary which will never match.
1099                // Instead, keep last bytes of boundary bytes size still in the body buffer to compare later.
1100
1101                // This many bytes can be copied to temp file if it'README.md size > 0
1102                // Here 2 is the size of length of \r\n which can be ignorable from the file.
1103                // Some uses single CRLF line break as well as double line breaks.
1104                // Don't move data from buffer to file if the length of the buffer is smaller than the
1105                // ending boundary + \r\n bytes.
1106
1107                let to_copy_size =
1108                    body_buffer.len() as i32 - (file_end_matching_bytes.len() as i32 + 2);
1109
1110                if to_copy_size > 0 {
1111                    let to_copy = &body_buffer[0..to_copy_size as usize];
1112
1113                    let write_result = temp_file.write_all(to_copy);
1114                    if !write_result.is_ok() {
1115                        return Err(MultipartFormDataError::Others(
1116                            "Error writing to temporary file",
1117                        ));
1118                    }
1119
1120                    // Remove copied bytes from the body buffer
1121                    *body_buffer = Vec::from(&body_buffer[to_copy_size as usize..]);
1122                    bytes_written += to_copy_size as usize;
1123                }
1124
1125                if form_part_limit.is_some()
1126                    && (bytes_written > form_part_limit.unwrap().max_size.unwrap())
1127                {
1128                    return Err(MultipartFormDataError::MaxFieldSizeExceed(
1129                        form_part.name.clone().unwrap().to_string(),
1130                        "The file is bigger than the maximum allowed size",
1131                    ));
1132                }
1133
1134                let request_new_chunk = reader.get_chunk();
1135
1136                match request_new_chunk {
1137                    Ok(new_chunk) => {
1138                        body_buffer.extend(new_chunk);
1139                    }
1140
1141                    Err(error) => {
1142                        return Err(error);
1143                    }
1144                }
1145            };
1146        }
1147    }
1148
1149    pub fn extract_form_value<T: StreamReader>(
1150        reader: &mut T,
1151        body_buffer: &mut Vec<u8>,
1152        boundary: &String,
1153        form_part: &mut FormPart,
1154        form_part_limit: Option<&FormPartLimit>,
1155    ) -> Result<FormPartResult, MultipartFormDataError> {
1156        let value_end_matcher = format!("\r\n--{}", boundary);
1157        let value_end_matching_bytes = value_end_matcher.as_bytes();
1158
1159        let mut value_buffer: Vec<u8> = Vec::new();
1160        let mut bytes_written: usize = 0;
1161
1162        let mut max_value_size = None;
1163        if form_part_limit.is_some() {
1164            max_value_size = form_part_limit.unwrap().max_size;
1165        }
1166
1167        loop {
1168            let end_index = body_buffer
1169                .windows(value_end_matching_bytes.len())
1170                .position(|window| window == value_end_matching_bytes);
1171
1172            if let Some(end_index) = end_index {
1173                // Either value is empty or value has already stored, but its end is just matched
1174                if end_index > 0 {
1175                    // Value end found
1176                    let mut to_copy_bytes = &body_buffer[..end_index];
1177
1178                    if to_copy_bytes.ends_with(b"\r\n") {
1179                        to_copy_bytes = &to_copy_bytes[0..to_copy_bytes.len() - 2]
1180                    }
1181
1182                    bytes_written += to_copy_bytes.len();
1183                    value_buffer.extend(to_copy_bytes);
1184
1185                    // Remove partial value end boundary from body buffer
1186                    *body_buffer =
1187                        Vec::from(&body_buffer[end_index + value_end_matching_bytes.len()..]);
1188                }
1189
1190                // Check if the value bytes written is larger than the limit specified
1191                if max_value_size.is_some() && max_value_size.unwrap() > bytes_written {
1192                    return Err(MultipartFormDataError::MaxFieldSizeExceed(
1193                        form_part.name.clone().unwrap().to_string(),
1194                        "The form field value size exceeds the limit specified",
1195                    ));
1196                }
1197
1198                // Check if it is the last form content or still there are others.
1199                // If it is the last form part content, it will contain --\r\n in next bytes.
1200                // If it is not last the last form part content, there will be \r\n in next bytes.
1201                // Till now, we don't know if body is completed or not.
1202
1203                let end_body_bytes = b"--\r\n";
1204                let next_part_bytes = b"\r\n";
1205                // Read exact 4 bytes if there is nothing in the body buffer else request required number of bytes.
1206                // 4 bytes should be there before completing request body.
1207
1208                if body_buffer.len() < 4 {
1209                    // Amount of bytes to read
1210                    let bytes_to_read = 4 - body_buffer.len();
1211
1212                    let request_new_chunk = reader.get_exact(bytes_to_read);
1213                    match request_new_chunk {
1214                        Ok(chunk) => {
1215                            body_buffer.extend(chunk);
1216                        }
1217                        Err(error) => {
1218                            return Err(error);
1219                        }
1220                    }
1221                }
1222
1223                // Compare --\r\n
1224                let body_end_compare = &body_buffer[0..4];
1225                if body_end_compare == end_body_bytes {
1226                    // All form part has been parsed
1227                    body_buffer.clear();
1228                    form_part.value = Some(value_buffer);
1229                    return Ok(FormPartResult::BodyCompleted);
1230                }
1231
1232                // Compare \r\n
1233                let form_part_next_compare = &body_buffer[0..2];
1234                if form_part_next_compare == next_part_bytes {
1235                    // Remove \r\n bytes from the body buffer
1236                    *body_buffer = Vec::from(&body_buffer[2..]);
1237                    form_part.value = Some(value_buffer);
1238                    return Ok(FormPartResult::CheckNext);
1239                }
1240
1241                // None of the condition is satisfied. Problem with the request body.
1242                return Err(MultipartFormDataError::ParsingError(
1243                    "Form content did not end with \r\n",
1244                ));
1245            } else {
1246                // Value end not found
1247
1248                // Copy scanned values to buffer except last bytes equal to the length of value_end_matching_bytes
1249                // We left last some bytes equal to value_end_matching_bytes because we need to compare again.
1250                // Here 2 is the size of length of \r\n which can be ignorable from the value.
1251                // Some uses single CRLF line break as well as double line breaks.
1252                let to_copy_size =
1253                    body_buffer.len() as i32 - (value_end_matching_bytes.len() as i32 + 2);
1254                if to_copy_size > 0 {
1255                    bytes_written += to_copy_size as usize;
1256
1257                    // This many bytes can be copied to value_buffer
1258                    value_buffer.extend(&body_buffer[..to_copy_size as usize]);
1259                    // Remove copied bytes form body buffer
1260                    *body_buffer = Vec::from(&body_buffer[to_copy_size as usize..]);
1261                }
1262
1263                if form_part_limit.is_some()
1264                    && (bytes_written > form_part_limit.unwrap().max_size.unwrap())
1265                {
1266                    return Err(MultipartFormDataError::MaxFieldSizeExceed(
1267                        form_part.name.clone().unwrap().to_string(),
1268                        "The form field value size exceeds the limit specified",
1269                    ));
1270                }
1271
1272                let request_new_chunk = reader.get_chunk();
1273                match request_new_chunk {
1274                    Ok(chunk) => {
1275                        body_buffer.extend(chunk);
1276                    }
1277
1278                    Err(error) => {
1279                        return Err(error);
1280                    }
1281                }
1282            }
1283        }
1284    }
1285}
1286
1287#[cfg(test)]
1288mod test {
1289    use crate::headers::Headers;
1290    use crate::parser::multipart::StreamReader;
1291    use crate::parser::multipart::{
1292        extract_form_part_body, extract_form_value, parse, parse_form_part_header, FormPart,
1293        Limits, MultipartFormDataError,
1294    };
1295    use rand::Rng;
1296    use std::collections::HashMap;
1297    use std::io::Read;
1298
1299    struct ChunkReader {
1300        body_bytes: Vec<u8>,
1301        bytes_read: usize,
1302    }
1303
1304    impl ChunkReader {
1305        fn new(body: &str, bytes_read: usize) -> Self {
1306            let body_bytes = body.as_bytes().to_vec();
1307
1308            return ChunkReader {
1309                body_bytes,
1310                bytes_read,
1311            };
1312        }
1313
1314        fn get_bytes_left(&self) -> usize {
1315            // Number of bytes that are left
1316            let bytes_left: i32 = self.body_bytes.len() as i32 - self.bytes_read as i32;
1317
1318            // Simulate socket broken
1319            if bytes_left > 0 {
1320                return bytes_left as usize;
1321            }
1322
1323            println!("Waiting forever...");
1324            println!("Socket connection broken.");
1325            return 0;
1326        }
1327    }
1328
1329    impl StreamReader for ChunkReader {
1330        fn get_chunk(&mut self) -> Result<Vec<u8>, MultipartFormDataError> {
1331            // Number of bytes that are left
1332            let bytes_left = self.get_bytes_left();
1333            if bytes_left == 0 {
1334                return Err(MultipartFormDataError::BodyReadEnd);
1335            }
1336
1337            let to_read = rand::thread_rng().gen_range(0..bytes_left + 1);
1338            let chunk = Vec::from(&self.body_bytes[self.bytes_read..&self.bytes_read + to_read]);
1339            self.bytes_read = self.bytes_read + to_read;
1340            return Ok(chunk);
1341        }
1342
1343        fn get_exact(&mut self, size: usize) -> Result<Vec<u8>, MultipartFormDataError> {
1344            let bytes_left = self.get_bytes_left();
1345            if bytes_left == 0 {
1346                println!("Waiting...");
1347                println!("Body is already read");
1348                return Err(MultipartFormDataError::BodyReadEnd);
1349            }
1350            let chunk = &self.body_bytes[self.bytes_read..self.bytes_read + size];
1351            self.bytes_read = self.bytes_read + size;
1352            return Ok(Vec::from(chunk));
1353        }
1354    }
1355
1356    const SAMPLE_BODY: &str = "----------------------------211628740782087473305609\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nJohn Doe\r\n----------------------------211628740782087473305609\r\nContent-Disposition: form-data; name=\"file\"; filename=\"a.txt\"\r\nContent-Type: text/plain\r\n\r\nhello\n\r\n----------------------------211628740782087473305609\r\nContent-Disposition: form-data; name=\"file\"; filename=\"a.txt\"\r\nContent-Type: text/plain\r\n\r\nhello\n\r\n----------------------------211628740782087473305609\r\nContent-Disposition: form-data; name=\"gender\"\r\n\r\nmale\r\n----------------------------211628740782087473305609--\r\n";
1357    const SAMPLE_BODY_2: &str = "--boundary123\r\nContent-Disposition: form-data; name=\"field1\"\r\n\r\nvalue1\r\n\r\n--boundary123\r\nContent-Disposition: form-data; name=\"file\"; filename=\"example.txt\"\r\nContent-Type: text/plain\r\n\r\nThis is the content of the file.\r\n--boundary123\r\nContent-Disposition: form-data; name=\"field2\"\r\n\r\nvalue2\r\n--boundary123--\r\n";
1358
1359    #[test]
1360    fn test_parser() {
1361        let mut reader = ChunkReader::new(SAMPLE_BODY_2, 0);
1362        let request_chunk_result = reader.get_exact(SAMPLE_BODY_2.len());
1363        assert_eq!(true, request_chunk_result.is_ok());
1364
1365        let mut headers: Headers = HashMap::new();
1366        // let content_type = vec!["multipart/form-data; boundary=--------------------------211628740782087473305609".to_string()];
1367        let content_type = vec!["multipart/form-data; boundary=boundary123".to_string()];
1368        headers.insert("Content-Type".to_string(), content_type);
1369
1370        let partial_body = request_chunk_result.unwrap();
1371        let parse_result = parse(partial_body, &headers, reader, Limits::none());
1372        match parse_result {
1373            Ok(form_parts) => {
1374                println!("Parsing success:");
1375
1376                for form_part in form_parts.iter() {
1377                    println!("Name: {}", form_part.name.as_ref().unwrap());
1378                    if form_part.value.as_ref().is_some() {
1379                        println!(
1380                            "Value: {:?}",
1381                            String::from_utf8(form_part.value.as_ref().unwrap().to_vec())
1382                        );
1383                    }
1384                }
1385            }
1386
1387            Err(error) => {
1388                println!("Error: {:?}", error);
1389            }
1390        }
1391    }
1392
1393    #[test]
1394    fn test_header_parser() {
1395        let header_sample_1 = "\r\nContent-Disposition: form-data; name=\"John Doe\"\r\n\r\n";
1396        let parsing_result = parse_form_part_header(header_sample_1.to_string());
1397        assert_eq!(true, parsing_result.is_ok());
1398        let form_part = parsing_result.unwrap();
1399        assert_eq!("John Doe", form_part.name.unwrap());
1400
1401        let header_sample_2 =
1402            "Content-Disposition: form-data; name=\"file\"; filename=\"a.txt\"\r\n\
1403        Content-Type: text/plain\r\n\r\n";
1404        let parsing_result = parse_form_part_header(header_sample_2.to_string());
1405        assert_eq!(true, parsing_result.is_ok());
1406        let form_part = parsing_result.unwrap();
1407
1408        assert_eq!(form_part.name.unwrap(), "file");
1409        assert_eq!(form_part.filename.unwrap(), "a.txt");
1410        assert_eq!(form_part.content_type.unwrap(), "text/plain");
1411    }
1412
1413    #[test]
1414    fn test_extract_file_body() {
1415        let sample_body = "John Doe\r\n\r\n----------------------------163905767229441796406063\r\nContent-Disposition...";
1416
1417        for _ in 0..10 {
1418            let mut form_part = FormPart {
1419                name: Some("file".to_string()),
1420                filename: Some("file.txt".to_string()),
1421                content_type: Some("text/html".to_string()),
1422                temp_file: None,
1423                value: None,
1424            };
1425
1426            let mut reader = ChunkReader::new(sample_body, 0);
1427            let mut body_buffer = reader.get_chunk().unwrap();
1428            // let mut body_buffer = Vec::new();
1429
1430            let boundary = "--------------------------163905767229441796406063".to_string();
1431            let result = extract_form_part_body(
1432                &mut reader,
1433                &mut body_buffer,
1434                &boundary,
1435                &mut form_part,
1436                &Limits::none(),
1437            );
1438            match result {
1439                Ok(res) => {
1440                    println!("{:?}", res);
1441                    let mut temp_file = &form_part.temp_file.unwrap();
1442                    // Example to copy temp file
1443                    // let filename = &form_part.filename.unwrap();
1444                    // let owned = filename.to_owned();
1445                    // let path = temp_file.path();
1446                    // std::fs::copy(path, owned).expect("Error copying");
1447
1448                    let mut content = String::new();
1449                    temp_file
1450                        .read_to_string(&mut content)
1451                        .expect("Error reading temporary file");
1452                    assert_eq!(content, "John Doe");
1453                }
1454
1455                Err(_) => {
1456                    panic!("Multipart body parsing returned error.");
1457                }
1458            }
1459        }
1460    }
1461
1462    #[test]
1463    fn test_extract_form_value() {
1464        let sample_body = "John Doe\r\n----------------------------163905767229441796406063\r\nContent-Disposition";
1465        let mut reader = ChunkReader::new(sample_body, 0);
1466        let mut body_buffer = reader.get_chunk().unwrap();
1467        let boundary = "--------------------------163905767229441796406063".to_string();
1468        let mut form_part = FormPart::empty();
1469
1470        let result = extract_form_value(
1471            &mut reader,
1472            &mut body_buffer,
1473            &boundary,
1474            &mut form_part,
1475            None,
1476        );
1477
1478        assert_eq!(true, result.is_ok());
1479        assert_eq!(b"John Doe", &form_part.value.unwrap().as_slice());
1480    }
1481}