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 = request_uri.replace(&FileExt::get_path_separator(), SYMBOL.slash).to_string();
190
191        let boxed_url_components = URL::parse_request_target(&url);
192        if boxed_url_components.is_err() {
193            let message = boxed_url_components.as_ref().err().unwrap().to_string();
194            // unfallable
195            println!("unexpected error, {}", message);
196        }
197
198        let components = boxed_url_components.unwrap();
199
200        let file_path_part = components.path.replace(SYMBOL.slash, &FileExt::get_path_separator());
201
202        let boxed_static_filepath = crate::app::controller::static_resource::static_fs_path(&file_path_part);
203        if boxed_static_filepath.is_err() {
204            let error = Error {
205                status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
206                message: boxed_static_filepath.err().unwrap()
207            };
208            eprintln!("{}", &error.message);
209            return Err(error);
210        }
211        let static_filepath = boxed_static_filepath.unwrap();
212
213        let boxed_metadata = metadata(&static_filepath);
214        if boxed_metadata.is_err() {
215            let error = Error {
216                status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
217                message: boxed_metadata.err().unwrap().to_string()
218            };
219            eprintln!("{}", &error.message);
220            return Err(error);
221        }
222
223        let md = boxed_metadata.unwrap();
224        if md.is_file() {
225            let mut path = static_filepath.as_str().to_string();
226
227            let boxed_is_link = FileExt::is_symlink(&static_filepath);
228            if boxed_is_link.is_err() {
229                let error = Error {
230                    status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
231                    message: boxed_is_link.err().unwrap()
232                };
233                eprintln!("{}", &error.message);
234                return Err(error);
235            }
236
237
238            let is_link = boxed_is_link.unwrap();
239            if is_link {
240                let boxed_points_to = FileExt::symlink_points_to(&static_filepath);
241                if boxed_points_to.is_err() {
242                    let error = Error {
243                        status_code_reason_phrase: STATUS_CODE_REASON_PHRASE.n500_internal_server_error,
244                        message: boxed_points_to.err().unwrap()
245                    };
246                    eprintln!("{}", &error.message);
247                    return Err(error);
248                }
249
250                let points_to = boxed_points_to.unwrap();
251                let reversed_link = &static_filepath.chars().rev().collect::<String>();
252
253                let mut symlink_directory = SYMBOL.empty_string.to_string();
254                let boxed_split = reversed_link.split_once(&FileExt::get_path_separator());
255                if boxed_split.is_some() {
256                    let (_filename, path) = boxed_split.unwrap();
257                    symlink_directory = path.chars().rev().collect::<String>();
258                }
259
260                let resolved_link = FileExt::resolve_symlink_path(&symlink_directory, &points_to).unwrap();
261                path = resolved_link;
262            }
263
264            let boxed_content_range_list = Range::parse_content_range(&path, md.len(), &range.value);
265            if boxed_content_range_list.is_ok() {
266                content_range_list = boxed_content_range_list.unwrap();
267            } else {
268                let error = boxed_content_range_list.err().unwrap();
269                return Err(error)
270            }
271        }
272
273        Ok(content_range_list)
274    }
275
276    pub fn _parse_multipart_body(cursor: &mut Cursor<&[u8]>, mut content_range_list: Vec<ContentRange>) -> Result<Vec<ContentRange>, String> {
277        // A loop, not recursion: one stack frame per line let a backend's
278        // multipart/byteranges body with thousands of lines overflow the
279        // stack and abort the process.
280        loop {
281
282            let mut buffer = Range::_parse_line_as_bytes(cursor);
283            let new_line_char_found = buffer.len() != 0;
284            let mut string = Range::_convert_bytes_array_to_string(buffer);
285
286            if !new_line_char_found {
287                return Ok(content_range_list)
288            };
289
290            let mut content_range: ContentRange = ContentRange {
291                unit: Range::BYTES.to_string(),
292                range: Range { start: 0, end: 0 },
293                size: "".to_string(),
294                body: vec![],
295                content_type: "".to_string()
296            };
297
298            let content_range_is_not_parsed = content_range.body.len() == 0;
299            let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
300            if string.starts_with(separator.as_str()) && content_range_is_not_parsed {
301                //read next line - Content-Type
302                buffer = Range::_parse_line_as_bytes(cursor);
303                string = Range::_convert_bytes_array_to_string(buffer);
304            }
305
306            let content_type_is_not_parsed = content_range.content_type.len() == 0;
307            if string.starts_with(Header::_CONTENT_TYPE) && content_type_is_not_parsed {
308                let content_type = Response::_parse_http_response_header_string(string.as_str());
309                content_range.content_type = content_type.value.trim().to_string();
310
311                //read next line - Content-Range
312                buffer = Range::_parse_line_as_bytes(cursor);
313                string = Range::_convert_bytes_array_to_string(buffer);
314            }
315
316            let content_range_is_not_parsed = content_range.size.len() == 0;
317            if string.starts_with(Header::_CONTENT_RANGE) && content_range_is_not_parsed {
318                let content_range_header = Response::_parse_http_response_header_string(string.as_str());
319
320                let boxed_result = Range::_parse_content_range_header_value(content_range_header.value);
321                if boxed_result.is_ok() {
322                    let (start, end, size) = boxed_result.unwrap();
323
324                    content_range.size = size.to_string();
325                    content_range.range.start = start as u64;
326                    content_range.range.end = end as u64;
327                } else {
328                    return Err(boxed_result.err().unwrap())
329                }
330
331
332
333                // read next line - empty line
334                buffer = Range::_parse_line_as_bytes(cursor);
335                string = Range::_convert_bytes_array_to_string(buffer);
336
337                if string.trim().len() > 0 {
338                    return Err(Range::_ERROR_NO_EMPTY_LINE_BETWEEN_CONTENT_RANGE_HEADER_AND_BODY.to_string());
339                }
340
341                // read next line - separator between content ranges
342                buffer = Range::_parse_line_as_bytes(cursor);
343                string = Range::_convert_bytes_array_to_string(buffer);
344            }
345
346            let content_range_is_parsed = content_range.size.len() != 0;
347            let content_type_is_parsed = content_range.content_type.len() != 0;
348            if content_range_is_parsed && content_type_is_parsed {
349                let mut body : Vec<u8> = vec![];
350                body = [body, string.as_bytes().to_vec()].concat();
351
352                let mut buf = Vec::from(string.as_bytes());
353                let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
354                while !buf.starts_with(separator.as_bytes()) {
355                    buf = vec![];
356                    cursor.read_until(b'\n', &mut buf).unwrap();
357                    let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
358                    if !buf.starts_with(separator.as_bytes()) {
359                        body = [body, buf.to_vec()].concat();
360                    }
361                }
362
363                let mut mutable_body : Vec<u8>  = body;
364                mutable_body.pop(); // remove /r
365                mutable_body.pop(); // remove /n
366
367
368                content_range.body = mutable_body;
369
370                content_range_list.push(content_range);
371            }
372
373        }
374    }
375
376    pub fn _parse_raw_content_range_header_value(unparsed_header_value: &str)-> Result<(i64, i64, i64), String> {
377        let lowercase_unparsed_header_value = unparsed_header_value.trim().to_lowercase();
378
379        let start : i64;
380        let end : i64;
381        let size : i64;
382
383
384        let boxed_split_without_bytes = lowercase_unparsed_header_value.split_once(SYMBOL.whitespace);
385        if boxed_split_without_bytes.is_none() {
386            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
387        }
388
389        let (bytes, without_bytes) = boxed_split_without_bytes.unwrap();
390        if !bytes.eq("bytes") {
391            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
392        }
393
394        let boxed_without_bytes = without_bytes.split_once(SYMBOL.hyphen);
395        if boxed_without_bytes.is_none() {
396            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
397        }
398
399        let (_start, _without_start) = boxed_without_bytes.unwrap();
400
401        let boxed_start = _start.parse::<i64>();
402        if boxed_start.is_err() {
403            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
404        }
405
406        start = boxed_start.unwrap();
407
408
409
410        let boxed_without_start = _without_start.split_once(SYMBOL.slash);
411        if boxed_without_start.is_none() {
412            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
413        }
414        let (_end, _size) = boxed_without_start.unwrap();
415
416        let boxed_end = _end.parse::<i64>();
417        if boxed_end.is_err() {
418            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
419        }
420
421        end = boxed_end.unwrap();
422
423        let boxed_size = _size.parse::<i64>();
424        if boxed_size.is_err() {
425            return Err(Range::_ERROR_UNABLE_TO_PARSE_CONTENT_RANGE.to_string())
426        }
427
428        size = boxed_size.unwrap();
429
430        Ok((start, end, size))
431    }
432
433    pub fn _parse_content_range_header_value(header_value: String) -> Result<(i64, i64, i64), String> {
434        let boxed_parse_result = Range::_parse_raw_content_range_header_value(&header_value);
435        if boxed_parse_result.is_err() {
436            return Err(boxed_parse_result.err().unwrap())
437        }
438        let (start, end, size) = boxed_parse_result.unwrap();
439
440        if start > end {
441            return Err(Range::ERROR_START_IS_AFTER_END_CONTENT_RANGE.to_string())
442        }
443
444        if start > size {
445            return Err(Range::ERROR_START_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE.to_string());
446        }
447        if end > size {
448            return  Err(Range::ERROR_END_IS_BIGGER_THAN_FILESIZE_CONTENT_RANGE.to_string());
449        }
450
451        Ok((start, end, size))
452    }
453
454    pub fn _parse_line_as_bytes(cursor: &mut Cursor<&[u8]>) -> Vec<u8> {
455        let mut buffer = vec![];
456        cursor.read_until(b'\n', &mut buffer).unwrap();
457        buffer
458    }
459
460    pub fn _convert_bytes_array_to_string(buffer: Vec<u8>) -> String {
461        let buffer_as_u8_array: &[u8] = &buffer;
462        String::from_utf8(Vec::from(buffer_as_u8_array)).unwrap()
463    }
464
465    /// Creates a `ContentRange` from raw bytes and a MIME type. The most common way to build a response body.
466    pub fn get_content_range(body: Vec<u8>, mime_type: String) -> ContentRange {
467        let length = body.len() as u64;
468        let content_range = ContentRange {
469            unit: Range::BYTES.to_string(),
470            range: Range { start: 0, end: length },
471            size: length.to_string(),
472            body,
473            content_type: mime_type
474        };
475
476        content_range
477    }
478
479    /// Creates a `ContentRange` by reading a file from disk. MIME type is detected from the extension.
480    pub fn get_content_range_of_a_file(filepath: &str) -> Result<ContentRange, String> {
481        let body: Vec<u8>;
482        let boxed_file = FileExt::read_file(filepath);
483        if boxed_file.is_err() {
484            let error = boxed_file.err().unwrap();
485            return Err(error);
486        }
487
488        body = boxed_file.unwrap();
489        let mime_type = MimeType::detect_mime_type(filepath);
490        let content_range = Range::get_content_range(body, mime_type);
491        Ok(content_range)
492    }
493
494
495    pub fn parse_multipart_body(cursor: &mut Cursor<&[u8]>,
496                                mut content_range_list: Vec<ContentRange>)
497        -> Result<Vec<ContentRange>, String> {
498
499        let boxed_line = Range::parse_line_as_bytes(cursor);
500        if boxed_line.is_err() {
501            let message = boxed_line.err().unwrap();
502            return Err(message);
503        }
504        let mut buffer = boxed_line.unwrap();
505
506
507        let new_line_char_found = buffer.len() != 0;
508
509
510        let boxed_line = Range::convert_bytes_array_to_string(buffer);
511        if boxed_line.is_err() {
512            let message = boxed_line.err().unwrap();
513            return Err(message);
514        }
515        let mut string = boxed_line.unwrap();
516
517        if !new_line_char_found {
518            return Ok(content_range_list)
519        };
520
521        let mut content_range: ContentRange = ContentRange {
522            unit: Range::BYTES.to_string(),
523            range: Range { start: 0, end: 0 },
524            size: "".to_string(),
525            body: vec![],
526            content_type: "".to_string()
527        };
528
529        let content_range_is_not_parsed = content_range.body.len() == 0;
530        let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
531        if string.starts_with(separator.as_str()) && content_range_is_not_parsed {
532            //read next line - Content-Type
533            let boxed_line = Range::parse_line_as_bytes(cursor);
534            if boxed_line.is_err() {
535                let message = boxed_line.err().unwrap();
536                return Err(message);
537            }
538            buffer = boxed_line.unwrap();
539
540            let boxed_line = Range::convert_bytes_array_to_string(buffer);
541            if boxed_line.is_err() {
542                let message = boxed_line.err().unwrap();
543                return Err(message);
544            }
545            string = boxed_line.unwrap();
546        }
547
548        let content_type_is_not_parsed = content_range.content_type.len() == 0;
549        if string.starts_with(Header::_CONTENT_TYPE) && content_type_is_not_parsed {
550            let boxed_content_type = Response::parse_http_response_header_string(string.as_str());
551            if boxed_content_type.is_err() {
552                let message = boxed_content_type.err().unwrap();
553                return Err(message);
554            }
555            let content_type = boxed_content_type.unwrap();
556
557            content_range.content_type = content_type.value.trim().to_string();
558
559            //read next line - Content-Range
560            let boxed_line = Range::parse_line_as_bytes(cursor);
561            if boxed_line.is_err() {
562                let message = boxed_line.err().unwrap();
563                return Err(message);
564            }
565            buffer = boxed_line.unwrap();
566
567            let boxed_line = Range::convert_bytes_array_to_string(buffer);
568            if boxed_line.is_err() {
569                let message = boxed_line.err().unwrap();
570                return Err(message);
571            }
572            string = boxed_line.unwrap();
573        }
574
575        let content_range_is_not_parsed = content_range.size.len() == 0;
576        if string.starts_with(Header::_CONTENT_RANGE) && content_range_is_not_parsed {
577            let content_range_header = Response::_parse_http_response_header_string(string.as_str());
578
579            let boxed_result = Range::_parse_content_range_header_value(content_range_header.value);
580            if boxed_result.is_ok() {
581                let (start, end, size) = boxed_result.unwrap();
582
583                content_range.size = size.to_string();
584                content_range.range.start = start as u64;
585                content_range.range.end = end as u64;
586            } else {
587                return Err(boxed_result.err().unwrap())
588            }
589
590
591
592            // read next line - empty line
593            let boxed_line = Range::parse_line_as_bytes(cursor);
594            if boxed_line.is_err() {
595                let message = boxed_line.err().unwrap();
596                return Err(message);
597            }
598            buffer = boxed_line.unwrap();
599
600            let boxed_line = Range::convert_bytes_array_to_string(buffer);
601            if boxed_line.is_err() {
602                let message = boxed_line.err().unwrap();
603                return Err(message);
604            }
605            string = boxed_line.unwrap();
606
607            if string.trim().len() > 0 {
608                return Err(Range::_ERROR_NO_EMPTY_LINE_BETWEEN_CONTENT_RANGE_HEADER_AND_BODY.to_string());
609            }
610
611            // read next line - separator between content ranges
612            let boxed_line = Range::parse_line_as_bytes(cursor);
613            if boxed_line.is_err() {
614                let message = boxed_line.err().unwrap();
615                return Err(message);
616            }
617            buffer = boxed_line.unwrap();
618
619            let boxed_line = Range::convert_bytes_array_to_string(buffer);
620            if boxed_line.is_err() {
621                let message = boxed_line.err().unwrap();
622                return Err(message);
623            }
624            string = boxed_line.unwrap();
625        }
626
627        let content_range_is_parsed = content_range.size.len() != 0;
628        let content_type_is_parsed = content_range.content_type.len() != 0;
629        if content_range_is_parsed && content_type_is_parsed {
630            let mut body : Vec<u8> = vec![];
631            body = [body, string.as_bytes().to_vec()].concat();
632
633            let mut buf = Vec::from(string.as_bytes());
634            let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
635            while !buf.starts_with(separator.as_bytes()) {
636                buf = vec![];
637                cursor.read_until(b'\n', &mut buf).unwrap();
638                let separator = [SYMBOL.hyphen, SYMBOL.hyphen, Range::STRING_SEPARATOR].join("");
639                if !buf.starts_with(separator.as_bytes()) {
640                    body = [body, buf.to_vec()].concat();
641                }
642            }
643
644            let mut mutable_body : Vec<u8>  = body;
645            mutable_body.pop(); // remove /r
646            mutable_body.pop(); // remove /n
647
648
649            content_range.body = mutable_body;
650
651            content_range_list.push(content_range);
652        }
653
654        let boxed_result = Range::_parse_multipart_body(cursor, content_range_list);
655        return if boxed_result.is_ok() {
656            Ok(boxed_result.unwrap())
657        } else {
658            let error = boxed_result.err().unwrap();
659            Err(error)
660        }
661
662    }
663
664    pub fn parse_multipart_body_with_boundary(cursor: &mut Cursor<&[u8]>,
665                                              mut content_range_list: Vec<ContentRange>,
666                                              boundary: String,
667                                              total_bytes: i32,
668                                              mut bytes_read: i32,
669                                              mut is_opening_boundary_read: bool)
670                                              -> Result<Vec<ContentRange>, String> {
671        // A loop, not recursion: one stack frame per line let a backend's
672        // multipart/byteranges body with thousands of lines overflow the
673        // stack and abort the process.
674        loop {
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        }
846    }
847
848    pub fn parse_line_as_bytes(cursor: &mut Cursor<&[u8]>) -> Result<Vec<u8>, String> {
849        let mut buffer = vec![];
850        let boxed_read = cursor.read_until(b'\n', &mut buffer);
851        if boxed_read.is_err() {
852            let message = boxed_read.err().unwrap().to_string();
853            return Err(message);
854        }
855        boxed_read.unwrap();
856        Ok(buffer)
857    }
858
859    pub fn convert_bytes_array_to_string(buffer: Vec<u8>) -> Result<String, String> {
860        let buffer_as_u8_array: &[u8] = &buffer;
861        let boxed_string = String::from_utf8(Vec::from(buffer_as_u8_array));
862        if boxed_string.is_err() {
863            let message = boxed_string.err().unwrap().to_string();
864            return Err(message);
865        }
866        let string = boxed_string.unwrap();
867        Ok(string)
868    }
869}
870
871