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 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 InvalidFormat(&'static str),
202 ContentLengthMissing(&'static str),
204 ParsingError(&'static str),
206 MaxBodySizeExceed(&'static str),
208 BodyReadEnd,
210 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 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 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 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 InvalidMultiPart(&'static str),
369 ParsingError(&'static str),
371 HeaderSizeExceed(&'static str),
373 MaxBodySizeExceed(&'static str),
375 MaxFieldSizeExceed(String, &'static str),
377 BodyReadEnd,
379 Others(&'static str),
381 }
382
383 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 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 pub bytes_read: usize,
413 pub body_ended: bool,
414 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 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 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 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; 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 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 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 let start_boundary = format!("--{}\r\n", boundary);
661 let start_boundary_bytes = start_boundary.as_bytes();
662
663 if body_buffer.len() <= start_boundary_bytes.len() {
665 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 body_buffer = Vec::from(&body_buffer[start_boundary_bytes.len()..]);
688
689 loop {
691 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 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 let mut form_part = header_parse_result.unwrap();
709
710 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 }
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 let extracted_boundary_slice = &body_buffer[0..start_boundary_bytes.len()];
748 return extracted_boundary_slice == start_boundary_bytes;
749 }
750
751 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 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 form_part_header_buffer.extend(&body_buffer[0..found_index]);
784
785 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 *body_buffer = Vec::from(&body_buffer[found_index + header_end_bytes.len()..]);
796 return Ok(form_part_header_buffer);
797 } else {
798 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 form_part_header_buffer.extend(header_end_bytes);
807 *body_buffer = Vec::from(&body_buffer[to_copy_to_header_buffer as usize..]);
809 }
810
811 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 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 for header_line in headers {
843 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 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 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 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 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 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 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 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 if let Some(body_end_index) = search_file_end {
998 if body_end_index > 0 {
1002 let mut bytes_to_copy = &body_buffer[0..body_end_index];
1005 bytes_written += bytes_to_copy.len();
1006
1007 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 *body_buffer =
1022 Vec::from(&body_buffer[body_end_index + file_end_matching_bytes.len()..]);
1023 }
1024
1025 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 let end_body_bytes = b"--\r\n";
1041 let next_part_bytes = b"\r\n";
1042 if body_buffer.len() < 4 {
1046 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 let body_end_compare = &body_buffer[0..4];
1062 if body_end_compare == end_body_bytes {
1063 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 let form_part_next_compare = &body_buffer[0..2];
1077 if form_part_next_compare == next_part_bytes {
1078 *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 return Err(MultipartFormDataError::ParsingError(
1093 "Form content did not end with \r\n",
1094 ));
1095 } else {
1096 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 *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 if end_index > 0 {
1175 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 *body_buffer =
1187 Vec::from(&body_buffer[end_index + value_end_matching_bytes.len()..]);
1188 }
1189
1190 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 let end_body_bytes = b"--\r\n";
1204 let next_part_bytes = b"\r\n";
1205 if body_buffer.len() < 4 {
1209 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 let body_end_compare = &body_buffer[0..4];
1225 if body_end_compare == end_body_bytes {
1226 body_buffer.clear();
1228 form_part.value = Some(value_buffer);
1229 return Ok(FormPartResult::BodyCompleted);
1230 }
1231
1232 let form_part_next_compare = &body_buffer[0..2];
1234 if form_part_next_compare == next_part_bytes {
1235 *body_buffer = Vec::from(&body_buffer[2..]);
1237 form_part.value = Some(value_buffer);
1238 return Ok(FormPartResult::CheckNext);
1239 }
1240
1241 return Err(MultipartFormDataError::ParsingError(
1243 "Form content did not end with \r\n",
1244 ));
1245 } else {
1246 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 value_buffer.extend(&body_buffer[..to_copy_size as usize]);
1259 *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 let bytes_left: i32 = self.body_bytes.len() as i32 - self.bytes_read as i32;
1317
1318 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 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=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 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 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}