Skip to main content

rust_web_server/range/
mod.rs

1#[cfg(test)]
2mod tests;
3
4#[cfg(test)]
5mod example;
6
7use std::io::prelude::*;
8use std::fs::{metadata};
9use std::io::{Cursor};
10use file_ext::FileExt;
11use crate::core::New;
12
13use crate::response::{Error, Response, STATUS_CODE_REASON_PHRASE};
14use crate::header::Header;
15use crate::mime_type::MimeType;
16use crate::symbol::SYMBOL;
17use crate::url::URL;
18
19/// A byte range within a resource (`start..end`).
20#[derive(PartialEq, Eq, Clone, Debug)]
21pub struct Range {
22    pub start: u64,
23    pub end: u64,
24}
25
26/// A single body part. `Response.content_range_list` holds one or more of these.
27///
28/// Build one with [`Range::get_content_range`] (in-memory bytes) or
29/// [`Range::get_content_range_of_a_file`] (file on disk).
30#[derive(PartialEq, Eq, Clone, Debug)]
31pub struct ContentRange {
32    /// Range unit — always `"bytes"`.
33    pub unit: String,
34    pub range: Range,
35    /// Total resource size as a string.
36    pub size: String,
37    /// Raw body bytes.
38    pub body: Vec<u8>,
39    /// MIME type for this part. Use [`MimeType`] constants or [`MimeType::detect_mime_type`].
40    pub content_type: String,
41}
42
43impl New for ContentRange {
44    fn new() -> Self {
45        ContentRange {
46            unit: Range::BYTES.to_string(),
47            range: Range { start: 0, end: 0 },
48            size: "".to_string(),
49            body: vec![],
50            content_type: "".to_string()
51        }
52    }
53}
54
55impl Range {
56    pub const STRING_SEPARATOR: &'static str = "String_separator";
57    pub const BOUNDARY: &'static str = "boundary";
58    pub const BYTERANGES: &'static str = "byteranges";
59    pub const MULTIPART: &'static str = "multipart";
60    pub const BYTES: &'static str = "bytes";
61    pub const MULTIPART_BYTERANGES_CONTENT_TYPE: &'static str = "multipart/byteranges; boundary=String_separator";
62
63
64    pub const _ERROR_NO_EMPTY_LINE_BETWEEN_CONTENT_RANGE_HEADER_AND_BODY: &'static str = "no empty line between content range headers and body";
65    pub const _ERROR_UNABLE_TO_PARSE_CONTENT_RANGE: &'static str = "unable to parse content-range";
66
67    pub const ERROR_START_IS_AFTER_END_CONTENT_RANGE: &'static str = "start is after end in content range";
68    pub const ERROR_START_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE: &'static str = "start is bigger than filesize in content range";
69    pub const ERROR_END_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE: &'static str = "end is bigger than filesize in content range";
70    pub const ERROR_MALFORMED_RANGE_HEADER_WRONG_UNIT: &'static str = "range header malformed, most likely you have an error in unit statement";
71
72    pub const ERROR_UNABLE_TO_PARSE_RANGE_START: &'static str = "unable to parse range start";
73    pub const ERROR_UNABLE_TO_PARSE_RANGE_END: &'static str = "unable to parse range end";
74
75
76    pub fn parse_range_in_content_range(filelength: u64, range_str: &str) -> Result<Range, Error> {
77        const START_INDEX: usize = 0;
78        const END_INDEX: usize = 1;
79
80        let mut range = Range { start: 0, end: filelength };
81        let parts: Vec<&str> = range_str.split(SYMBOL.hyphen).collect();
82
83        let mut start_range_not_provided = true;
84        for (i, part) in parts.iter().enumerate() {
85
86            let num = part.trim();
87            let length = num.len();
88
89            if i == START_INDEX && length != 0 {
90                start_range_not_provided = false;
91            }
92            if i == START_INDEX && length != 0 {
93                let boxed_start  = num.parse();
94                if boxed_start.is_ok() {
95                    range.start = boxed_start.unwrap()
96                } else {
97                    let message = Range::ERROR_UNABLE_TO_PARSE_RANGE_START.to_string();
98                    let error = Error {
99                        status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
100                        message: message.to_string()
101                    };
102                    return Err(error)
103                }
104            }
105            if i == END_INDEX && length != 0 {
106                let boxed_end  = num.parse();
107                if boxed_end.is_ok() {
108                    range.end = boxed_end.unwrap()
109                } else {
110                    let message = Range::ERROR_UNABLE_TO_PARSE_RANGE_END.to_string();
111                    let error = Error {
112                        status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
113                        message: message.to_string()
114                    };
115                    return Err(error)
116                }
117            }
118            if i == END_INDEX && length != 0 && start_range_not_provided {
119                let boxed_parse = num.parse();
120                if boxed_parse.is_err() {
121                    let error = Error {
122                        status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
123                        message: Range::ERROR_UNABLE_TO_PARSE_RANGE_END.to_string()
124                    };
125                    return Err(error)
126                }
127                let num_usize : u64 = boxed_parse.unwrap();
128                range.start = filelength - num_usize;
129                range.end = filelength;
130            }
131
132            if range.end > filelength {
133                let message = Range::ERROR_END_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE.to_string();
134                let error = Error {
135                    status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
136                    message,
137                };
138                return Err(error);
139            }
140
141            if range.start > filelength {
142                let message = Range::ERROR_START_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE.to_string();
143                let error = Error {
144                    status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
145                    message,
146                };
147                return Err(error);
148            }
149
150            if range.start > range.end {
151                let message = Range::ERROR_START_IS_AFTER_END_CONTENT_RANGE.to_string();
152                let error = Error {
153                    status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
154                    message,
155                };
156                return Err(error);
157            }
158
159
160
161        }
162        Ok(range)
163    }
164
165    pub fn parse_content_range(filepath: &str, filelength: u64, raw_range_value: &str) -> Result<Vec<ContentRange>, Error> {
166        const INDEX_AFTER_UNIT_DECLARATION : usize = 1;
167        let mut content_range_list: Vec<ContentRange> = vec![];
168
169        let prefix = [Range::BYTES, SYMBOL.equals].join("");
170        if !raw_range_value.starts_with(prefix.as_str()) {
171            let message = Range::ERROR_MALFORMED_RANGE_HEADER_WRONG_UNIT.to_string();
172            let error = Error {
173                status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
174                message,
175            };
176            return Err(error);
177        }
178
179        let split_raw_range_value: Vec<&str> = raw_range_value.split(SYMBOL.equals).collect();
180        let boxed_raw_bytes = split_raw_range_value.get(INDEX_AFTER_UNIT_DECLARATION);
181        if boxed_raw_bytes.is_none() {
182            let message = Range::ERROR_UNABLE_TO_PARSE_RANGE_START.to_string();
183            let error = Error {
184                status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
185                message: message.to_string()
186            };
187            return Err(error)
188        }
189
190        let raw_bytes = boxed_raw_bytes.unwrap();
191
192        let bytes: Vec<&str> = raw_bytes.split(SYMBOL.comma).collect();
193        for byte in bytes {
194            let boxed_range = Range::parse_range_in_content_range(filelength, byte);
195            if boxed_range.is_ok() {
196                let range = boxed_range.unwrap();
197                let boxed_read = FileExt::read_file_partially(filepath, range.start, range.end);
198                if boxed_read.is_ok() {
199
200                    let content_type = MimeType::detect_mime_type(filepath);
201                    let body = boxed_read.unwrap();
202                    let content_range = ContentRange {
203                        unit: Range::BYTES.to_string(),
204                        range,
205                        size: filelength.to_string(),
206                        body,
207                        content_type,
208                    };
209                    content_range_list.push(content_range);
210                } else {
211                    let error : Error = Error {
212                        status_code_reason_phrase:  STATUS_CODE_REASON_PHRASE.n416_range_not_satisfiable,
213                        message: boxed_read.err().unwrap().to_string()
214                    };
215                    return Err(error)
216                }
217            } else {
218                let error : Error = boxed_range.err().unwrap();
219                return Err(error);
220            }
221        }
222        Ok(content_range_list)
223    }
224
225    pub fn get_content_range_list(request_uri: &str, range: &Header) -> Result<Vec<ContentRange>, Error> {
226        let mut content_range_list : Vec<ContentRange> = vec![];
227
228        let url_array = ["http://", "localhost", &request_uri.replace(&FileExt::get_path_separator(), SYMBOL.slash)];
229        let url = url_array.join(SYMBOL.empty_string);
230
231        let boxed_url_components = URL::parse(&url);
232        if boxed_url_components.is_err() {
233            let message = boxed_url_components.as_ref().err().unwrap().to_string();
234            // unfallable
235            println!("unexpected error, {}", message);
236        }
237
238        let components = boxed_url_components.unwrap();
239
240        let file_path_part = components.path.replace(SYMBOL.slash, &FileExt::get_path_separator());
241
242        let boxed_static_filepath = FileExt::get_static_filepath(&file_path_part);
243        if boxed_static_filepath.is_err() {
244            let error = Error {
245                status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
246                message: boxed_static_filepath.err().unwrap()
247            };
248            eprintln!("{}", &error.message);
249            return Err(error);
250        }
251        let static_filepath = boxed_static_filepath.unwrap();
252
253        let boxed_metadata = metadata(&static_filepath);
254        if boxed_metadata.is_err() {
255            let error = Error {
256                status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
257                message: boxed_metadata.err().unwrap().to_string()
258            };
259            eprintln!("{}", &error.message);
260            return Err(error);
261        }
262
263        let md = boxed_metadata.unwrap();
264        if md.is_file() {
265            let mut path = static_filepath.as_str().to_string();
266
267            let boxed_is_link = FileExt::is_symlink(&static_filepath);
268            if boxed_is_link.is_err() {
269                let error = Error {
270                    status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
271                    message: boxed_is_link.err().unwrap()
272                };
273                eprintln!("{}", &error.message);
274                return Err(error);
275            }
276
277
278            let is_link = boxed_is_link.unwrap();
279            if is_link {
280                let boxed_points_to = FileExt::symlink_points_to(&static_filepath);
281                if boxed_points_to.is_err() {
282                    let error = Error {
283                        status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
284                        message: boxed_points_to.err().unwrap()
285                    };
286                    eprintln!("{}", &error.message);
287                    return Err(error);
288                }
289
290                let points_to = boxed_points_to.unwrap();
291                let reversed_link = &static_filepath.chars().rev().collect::<String>();
292
293                let mut symlink_directory = SYMBOL.empty_string.to_string();
294                let boxed_split = reversed_link.split_once(&FileExt::get_path_separator());
295                if boxed_split.is_some() {
296                    let (_filename, path) = boxed_split.unwrap();
297                    symlink_directory = path.chars().rev().collect::<String>();
298                }
299
300                let resolved_link = FileExt::resolve_symlink_path(&symlink_directory, &points_to).unwrap();
301                path = resolved_link;
302            }
303
304            let boxed_content_range_list = Range::parse_content_range(&path, md.len(), &range.value);
305            if boxed_content_range_list.is_ok() {
306                content_range_list = boxed_content_range_list.unwrap();
307            } else {
308                let error = boxed_content_range_list.err().unwrap();
309                return Err(error)
310            }
311        }
312
313        Ok(content_range_list)
314    }
315
316    pub fn _parse_multipart_body(cursor: &mut Cursor<&[u8]>, mut content_range_list: Vec<ContentRange>) -> Result<Vec<ContentRange>, String> {
317
318        let mut buffer = Range::_parse_line_as_bytes(cursor);
319        let new_line_char_found = buffer.len() != 0;
320        let mut string = Range::_convert_bytes_array_to_string(buffer);
321
322        if !new_line_char_found {
323            return Ok(content_range_list)
324        };
325
326        let mut content_range: ContentRange = ContentRange {
327            unit: Range::BYTES.to_string(),
328            range: Range { start: 0, end: 0 },
329            size: "".to_string(),
330            body: vec![],
331            content_type: "".to_string()
332        };
333
334        let content_range_is_not_parsed = content_range.body.len() == 0;
335        let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
336        if string.starts_with(separator.as_str()) && content_range_is_not_parsed {
337            //read next line - Content-Type
338            buffer = Range::_parse_line_as_bytes(cursor);
339            string = Range::_convert_bytes_array_to_string(buffer);
340        }
341
342        let content_type_is_not_parsed = content_range.content_type.len() == 0;
343        if string.starts_with(Header::_CONTENT_TYPE) && content_type_is_not_parsed {
344            let content_type = Response::_parse_http_response_header_string(string.as_str());
345            content_range.content_type = content_type.value.trim().to_string();
346
347            //read next line - Content-Range
348            buffer = Range::_parse_line_as_bytes(cursor);
349            string = Range::_convert_bytes_array_to_string(buffer);
350        }
351
352        let content_range_is_not_parsed = content_range.size.len() == 0;
353        if string.starts_with(Header::_CONTENT_RANGE) && content_range_is_not_parsed {
354            let content_range_header = Response::_parse_http_response_header_string(string.as_str());
355
356            let boxed_result = Range::_parse_content_range_header_value(content_range_header.value);
357            if boxed_result.is_ok() {
358                let (start, end, size) = boxed_result.unwrap();
359
360                content_range.size = size.to_string();
361                content_range.range.start = start as u64;
362                content_range.range.end = end as u64;
363            } else {
364                return Err(boxed_result.err().unwrap())
365            }
366
367
368
369            // read next line - empty line
370            buffer = Range::_parse_line_as_bytes(cursor);
371            string = Range::_convert_bytes_array_to_string(buffer);
372
373            if string.trim().len() > 0 {
374                return Err(Range::_ERROR_NO_EMPTY_LINE_BETWEEN_CONTENT_RANGE_HEADER_AND_BODY.to_string());
375            }
376
377            // read next line - separator between content ranges
378            buffer = Range::_parse_line_as_bytes(cursor);
379            string = Range::_convert_bytes_array_to_string(buffer);
380        }
381
382        let content_range_is_parsed = content_range.size.len() != 0;
383        let content_type_is_parsed = content_range.content_type.len() != 0;
384        if content_range_is_parsed && content_type_is_parsed {
385            let mut body : Vec<u8> = vec![];
386            body = [body, string.as_bytes().to_vec()].concat();
387
388            let mut buf = Vec::from(string.as_bytes());
389            let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
390            while !buf.starts_with(separator.as_bytes()) {
391                buf = vec![];
392                cursor.read_until(b'\n', &mut buf).unwrap();
393                let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
394                if !buf.starts_with(separator.as_bytes()) {
395                    body = [body, buf.to_vec()].concat();
396                }
397            }
398
399            let mut mutable_body : Vec<u8>  = body;
400            mutable_body.pop(); // remove /r
401            mutable_body.pop(); // remove /n
402
403
404            content_range.body = mutable_body;
405
406            content_range_list.push(content_range);
407        }
408
409        let boxed_result = Range::_parse_multipart_body(cursor, content_range_list);
410        return if boxed_result.is_ok() {
411            Ok(boxed_result.unwrap())
412        } else {
413            let error = boxed_result.err().unwrap();
414            Err(error)
415        }
416
417    }
418
419    pub fn _parse_raw_content_range_header_value(unparsed_header_value: &str)-> Result<(i64, i64, i64), String> {
420        let lowercase_unparsed_header_value = unparsed_header_value.trim().to_lowercase();
421
422        let start : i64;
423        let end : i64;
424        let size : i64;
425
426
427        let boxed_split_without_bytes = lowercase_unparsed_header_value.split_once(SYMBOL.whitespace);
428        if boxed_split_without_bytes.is_none() {
429            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
430        }
431
432        let (bytes, without_bytes) = boxed_split_without_bytes.unwrap();
433        if !bytes.eq("bytes") {
434            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
435        }
436
437        let boxed_without_bytes = without_bytes.split_once(SYMBOL.hyphen);
438        if boxed_without_bytes.is_none() {
439            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
440        }
441
442        let (_start, _without_start) = boxed_without_bytes.unwrap();
443
444        let boxed_start = _start.parse::<i64>();
445        if boxed_start.is_err() {
446            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
447        }
448
449        start = boxed_start.unwrap();
450
451
452
453        let boxed_without_start = _without_start.split_once(SYMBOL.slash);
454        if boxed_without_start.is_none() {
455            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
456        }
457        let (_end, _size) = boxed_without_start.unwrap();
458
459        let boxed_end = _end.parse::<i64>();
460        if boxed_end.is_err() {
461            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
462        }
463
464        end = boxed_end.unwrap();
465
466        let boxed_size = _size.parse::<i64>();
467        if boxed_size.is_err() {
468            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
469        }
470
471        size = boxed_size.unwrap();
472
473        Ok((start, end, size))
474    }
475
476    pub fn _parse_content_range_header_value(header_value: String) -> Result<(i64, i64, i64), String> {
477        let boxed_parse_result = Range::_parse_raw_content_range_header_value(&header_value);
478        if boxed_parse_result.is_err() {
479            return Err(boxed_parse_result.err().unwrap())
480        }
481        let (start, end, size) = boxed_parse_result.unwrap();
482
483        if start > end {
484            return Err(Range::ERROR_START_IS_AFTER_END_CONTENT_RANGE.to_string())
485        }
486
487        if start > size {
488            return Err(Range::ERROR_START_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE.to_string());
489        }
490        if end > size {
491            return  Err(Range::ERROR_END_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE.to_string());
492        }
493
494        Ok((start, end, size))
495    }
496
497    pub fn _parse_line_as_bytes(cursor: &mut Cursor<&[u8]>) -> Vec<u8> {
498        let mut buffer = vec![];
499        cursor.read_until(b'\n', &mut buffer).unwrap();
500        buffer
501    }
502
503    pub fn _convert_bytes_array_to_string(buffer: Vec<u8>) -> String {
504        let buffer_as_u8_array: &[u8] = &buffer;
505        String::from_utf8(Vec::from(buffer_as_u8_array)).unwrap()
506    }
507
508    /// Creates a `ContentRange` from raw bytes and a MIME type. The most common way to build a response body.
509    pub fn get_content_range(body: Vec<u8>, mime_type: String) -> ContentRange {
510        let length = body.len() as u64;
511        let content_range = ContentRange {
512            unit: Range::BYTES.to_string(),
513            range: Range { start: 0, end: length },
514            size: length.to_string(),
515            body,
516            content_type: mime_type
517        };
518
519        content_range
520    }
521
522    /// Creates a `ContentRange` by reading a file from disk. MIME type is detected from the extension.
523    pub fn get_content_range_of_a_file(filepath: &str) -> Result<ContentRange, String> {
524        let body: Vec<u8>;
525        let boxed_file = FileExt::read_file(filepath);
526        if boxed_file.is_err() {
527            let error = boxed_file.err().unwrap();
528            return Err(error);
529        }
530
531        body = boxed_file.unwrap();
532        let mime_type = MimeType::detect_mime_type(filepath);
533        let content_range = Range::get_content_range(body, mime_type);
534        Ok(content_range)
535    }
536
537
538    pub fn parse_multipart_body(cursor: &mut Cursor<&[u8]>,
539                                mut content_range_list: Vec<ContentRange>)
540        -> Result<Vec<ContentRange>, String> {
541
542        let boxed_line = Range::parse_line_as_bytes(cursor);
543        if boxed_line.is_err() {
544            let message = boxed_line.err().unwrap();
545            return Err(message);
546        }
547        let mut buffer = boxed_line.unwrap();
548
549
550        let new_line_char_found = buffer.len() != 0;
551
552
553        let boxed_line = Range::convert_bytes_array_to_string(buffer);
554        if boxed_line.is_err() {
555            let message = boxed_line.err().unwrap();
556            return Err(message);
557        }
558        let mut string = boxed_line.unwrap();
559
560        if !new_line_char_found {
561            return Ok(content_range_list)
562        };
563
564        let mut content_range: ContentRange = ContentRange {
565            unit: Range::BYTES.to_string(),
566            range: Range { start: 0, end: 0 },
567            size: "".to_string(),
568            body: vec![],
569            content_type: "".to_string()
570        };
571
572        let content_range_is_not_parsed = content_range.body.len() == 0;
573        let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
574        if string.starts_with(separator.as_str()) && content_range_is_not_parsed {
575            //read next line - Content-Type
576            let boxed_line = Range::parse_line_as_bytes(cursor);
577            if boxed_line.is_err() {
578                let message = boxed_line.err().unwrap();
579                return Err(message);
580            }
581            buffer = boxed_line.unwrap();
582
583            let boxed_line = Range::convert_bytes_array_to_string(buffer);
584            if boxed_line.is_err() {
585                let message = boxed_line.err().unwrap();
586                return Err(message);
587            }
588            string = boxed_line.unwrap();
589        }
590
591        let content_type_is_not_parsed = content_range.content_type.len() == 0;
592        if string.starts_with(Header::_CONTENT_TYPE) && content_type_is_not_parsed {
593            let boxed_content_type = Response::parse_http_response_header_string(string.as_str());
594            if boxed_content_type.is_err() {
595                let message = boxed_content_type.err().unwrap();
596                return Err(message);
597            }
598            let content_type = boxed_content_type.unwrap();
599
600            content_range.content_type = content_type.value.trim().to_string();
601
602            //read next line - Content-Range
603            let boxed_line = Range::parse_line_as_bytes(cursor);
604            if boxed_line.is_err() {
605                let message = boxed_line.err().unwrap();
606                return Err(message);
607            }
608            buffer = boxed_line.unwrap();
609
610            let boxed_line = Range::convert_bytes_array_to_string(buffer);
611            if boxed_line.is_err() {
612                let message = boxed_line.err().unwrap();
613                return Err(message);
614            }
615            string = boxed_line.unwrap();
616        }
617
618        let content_range_is_not_parsed = content_range.size.len() == 0;
619        if string.starts_with(Header::_CONTENT_RANGE) && content_range_is_not_parsed {
620            let content_range_header = Response::_parse_http_response_header_string(string.as_str());
621
622            let boxed_result = Range::_parse_content_range_header_value(content_range_header.value);
623            if boxed_result.is_ok() {
624                let (start, end, size) = boxed_result.unwrap();
625
626                content_range.size = size.to_string();
627                content_range.range.start = start as u64;
628                content_range.range.end = end as u64;
629            } else {
630                return Err(boxed_result.err().unwrap())
631            }
632
633
634
635            // read next line - empty line
636            let boxed_line = Range::parse_line_as_bytes(cursor);
637            if boxed_line.is_err() {
638                let message = boxed_line.err().unwrap();
639                return Err(message);
640            }
641            buffer = boxed_line.unwrap();
642
643            let boxed_line = Range::convert_bytes_array_to_string(buffer);
644            if boxed_line.is_err() {
645                let message = boxed_line.err().unwrap();
646                return Err(message);
647            }
648            string = boxed_line.unwrap();
649
650            if string.trim().len() > 0 {
651                return Err(Range::_ERROR_NO_EMPTY_LINE_BETWEEN_CONTENT_RANGE_HEADER_AND_BODY.to_string());
652            }
653
654            // read next line - separator between content ranges
655            let boxed_line = Range::parse_line_as_bytes(cursor);
656            if boxed_line.is_err() {
657                let message = boxed_line.err().unwrap();
658                return Err(message);
659            }
660            buffer = boxed_line.unwrap();
661
662            let boxed_line = Range::convert_bytes_array_to_string(buffer);
663            if boxed_line.is_err() {
664                let message = boxed_line.err().unwrap();
665                return Err(message);
666            }
667            string = boxed_line.unwrap();
668        }
669
670        let content_range_is_parsed = content_range.size.len() != 0;
671        let content_type_is_parsed = content_range.content_type.len() != 0;
672        if content_range_is_parsed && content_type_is_parsed {
673            let mut body : Vec<u8> = vec![];
674            body = [body, string.as_bytes().to_vec()].concat();
675
676            let mut buf = Vec::from(string.as_bytes());
677            let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
678            while !buf.starts_with(separator.as_bytes()) {
679                buf = vec![];
680                cursor.read_until(b'\n', &mut buf).unwrap();
681                let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
682                if !buf.starts_with(separator.as_bytes()) {
683                    body = [body, buf.to_vec()].concat();
684                }
685            }
686
687            let mut mutable_body : Vec<u8>  = body;
688            mutable_body.pop(); // remove /r
689            mutable_body.pop(); // remove /n
690
691
692            content_range.body = mutable_body;
693
694            content_range_list.push(content_range);
695        }
696
697        let boxed_result = Range::_parse_multipart_body(cursor, content_range_list);
698        return if boxed_result.is_ok() {
699            Ok(boxed_result.unwrap())
700        } else {
701            let error = boxed_result.err().unwrap();
702            Err(error)
703        }
704
705    }
706
707    pub fn parse_multipart_body_with_boundary(cursor: &mut Cursor<&[u8]>,
708                                              mut content_range_list: Vec<ContentRange>,
709                                              boundary: String,
710                                              total_bytes: i32,
711                                              mut bytes_read: i32,
712                                              mut is_opening_boundary_read: bool)
713                                              -> Result<Vec<ContentRange>, String> {
714
715        let mut buffer = vec![];
716        let boxed_read = cursor.read_until(b'\n', &mut buffer);
717        if boxed_read.is_err() {
718            let message = boxed_read.err().unwrap().to_string();
719            return Err(message);
720        }
721
722        let bytes_offset = boxed_read.unwrap();
723        bytes_read = bytes_read + bytes_offset as i32;
724        if bytes_read == total_bytes {
725            // end of stream
726        }
727
728
729        let new_line_char_found = buffer.len() != 0;
730
731
732        let boxed_line = Range::convert_bytes_array_to_string(buffer);
733        if boxed_line.is_err() {
734            let message = boxed_line.err().unwrap();
735            return Err(message);
736        }
737        let mut string = boxed_line.unwrap();
738
739        if !new_line_char_found {
740            return Ok(content_range_list)
741        };
742
743        let mut content_range: ContentRange = ContentRange::new();
744
745        let content_range_is_not_parsed = content_range.body.len() == 0;
746
747        if string.trim().len() != 0 && !is_opening_boundary_read && !string.contains(boundary.as_str()) {
748            return Err("Response body doesn't start with a boundary".to_string())
749        }
750
751        if string.contains(boundary.as_str()) && content_range_is_not_parsed {
752            if !is_opening_boundary_read {
753                is_opening_boundary_read = true;
754            }
755            //read next line - Content-Type
756            let boxed_line = Range::parse_line_as_bytes(cursor);
757            if boxed_line.is_err() {
758                let message = boxed_line.err().unwrap();
759                return Err(message);
760            }
761            buffer = boxed_line.unwrap();
762
763            let boxed_line = Range::convert_bytes_array_to_string(buffer);
764            if boxed_line.is_err() {
765                let message = boxed_line.err().unwrap();
766                return Err(message);
767            }
768            string = boxed_line.unwrap();
769        }
770
771        let content_type_is_not_parsed = content_range.content_type.len() == 0;
772        if string.starts_with(Header::_CONTENT_TYPE) && content_type_is_not_parsed {
773            let boxed_content_type = Response::parse_http_response_header_string(string.as_str());
774            if boxed_content_type.is_err() {
775                let message = boxed_content_type.err().unwrap();
776                return Err(message);
777            }
778            let content_type = boxed_content_type.unwrap();
779
780            content_range.content_type = content_type.value.trim().to_string();
781
782            //read next line - Content-Range
783            let boxed_line = Range::parse_line_as_bytes(cursor);
784            if boxed_line.is_err() {
785                let message = boxed_line.err().unwrap();
786                return Err(message);
787            }
788            buffer = boxed_line.unwrap();
789
790            let boxed_line = Range::convert_bytes_array_to_string(buffer);
791            if boxed_line.is_err() {
792                let message = boxed_line.err().unwrap();
793                return Err(message);
794            }
795            string = boxed_line.unwrap();
796        }
797
798        let content_range_is_not_parsed = content_range.size.len() == 0;
799        if string.starts_with(Header::_CONTENT_RANGE) && content_range_is_not_parsed {
800            let content_range_header = Response::_parse_http_response_header_string(string.as_str());
801
802            let boxed_result = Range::_parse_content_range_header_value(content_range_header.value);
803            if boxed_result.is_ok() {
804                let (start, end, size) = boxed_result.unwrap();
805
806                content_range.size = size.to_string();
807                content_range.range.start = start as u64;
808                content_range.range.end = end as u64;
809            } else {
810                return Err(boxed_result.err().unwrap())
811            }
812
813
814
815            // read next line - empty line
816            let boxed_line = Range::parse_line_as_bytes(cursor);
817            if boxed_line.is_err() {
818                let message = boxed_line.err().unwrap();
819                return Err(message);
820            }
821            buffer = boxed_line.unwrap();
822
823            let boxed_line = Range::convert_bytes_array_to_string(buffer);
824            if boxed_line.is_err() {
825                let message = boxed_line.err().unwrap();
826                return Err(message);
827            }
828            string = boxed_line.unwrap();
829
830            if string.trim().len() > 0 {
831                return Err(Range::_ERROR_NO_EMPTY_LINE_BETWEEN_CONTENT_RANGE_HEADER_AND_BODY.to_string());
832            }
833
834        }
835
836        let content_range_is_parsed = content_range.size.len() != 0;
837        let content_type_is_parsed = content_range.content_type.len() != 0;
838        if content_range_is_parsed && content_type_is_parsed {
839            let mut body : Vec<u8> = vec![];
840
841            let mut is_not_boundary = true;
842
843            while is_not_boundary {
844                let mut _bytes_offset = 0;
845                let mut buf: Vec<u8> = vec![];
846                let boxed_read = cursor.read_until(b'\n', &mut buf);
847                if boxed_read.is_err() {
848                    return Err("Unable to read from stream".to_string());
849                }
850                _bytes_offset = boxed_read.unwrap();
851                bytes_read = bytes_read + _bytes_offset as i32;
852
853
854                let boxed_line = Range::convert_bytes_array_to_string(buf.clone());
855                if boxed_line.is_err() {
856                    // non utf-8 body, continue
857                    body = [body, buf.to_vec()].concat();
858                    continue;
859                }
860
861                string = boxed_line.unwrap();
862
863                is_not_boundary = !string.contains(boundary.as_str());
864
865                if is_not_boundary {
866                    body = [body, buf.to_vec()].concat();
867                    if (bytes_read == total_bytes) || _bytes_offset == 0 {
868                        return Err("Unable to parse multipart form body, reached the end of stream and it does not contain boundary".to_string());
869                    }
870                }
871
872            }
873
874            let mut mutable_body : Vec<u8>  = body;
875            mutable_body.pop(); // remove /r
876            mutable_body.pop(); // remove /n
877
878
879            content_range.body = mutable_body;
880
881            content_range_list.push(content_range);
882        }
883
884        let boxed_result = Range::parse_multipart_body_with_boundary(
885            cursor,
886            content_range_list,
887            boundary,
888            total_bytes,
889            bytes_read,
890            is_opening_boundary_read);
891        return if boxed_result.is_ok() {
892            Ok(boxed_result.unwrap())
893        } else {
894            let error = boxed_result.err().unwrap();
895            Err(error)
896        }
897
898    }
899
900    pub fn parse_line_as_bytes(cursor: &mut Cursor<&[u8]>) -> Result<Vec<u8>, String> {
901        let mut buffer = vec![];
902        let boxed_read = cursor.read_until(b'\n', &mut buffer);
903        if boxed_read.is_err() {
904            let message = boxed_read.err().unwrap().to_string();
905            return Err(message);
906        }
907        boxed_read.unwrap();
908        Ok(buffer)
909    }
910
911    pub fn convert_bytes_array_to_string(buffer: Vec<u8>) -> Result<String, String> {
912        let buffer_as_u8_array: &[u8] = &buffer;
913        let boxed_string = String::from_utf8(Vec::from(buffer_as_u8_array));
914        if boxed_string.is_err() {
915            let message = boxed_string.err().unwrap().to_string();
916            return Err(message);
917        }
918        let string = boxed_string.unwrap();
919        Ok(string)
920    }
921}
922
923