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