1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
use crate::http::objects::get::GetObjectRequest;

use crate::http::Escape;
use reqwest::{Client, RequestBuilder};

#[derive(Default)]
pub struct Range(pub Option<u64>, pub Option<u64>);

impl Range {
    /// Range: bytes=0-1999 (first 2000 bytes)
    /// Range: bytes=-2000 (last 2000 bytes)
    /// Range: bytes=2000- (from byte 2000 to end of file)
    fn with_header(&self, builder: RequestBuilder) -> RequestBuilder {
        if let Some(from) = self.0 {
            if let Some(to) = self.1 {
                builder.header("Range", format!("bytes={}-{}", from, to))
            } else {
                builder.header("Range", format!("bytes={}-", from))
            }
        } else if let Some(reverse_from) = self.1 {
            builder.header("Range", format!("bytes=-{}", reverse_from))
        } else {
            builder
        }
    }
}

pub(crate) fn build(base_url: &str, client: &Client, req: &GetObjectRequest, range: &Range) -> RequestBuilder {
    let url = format!("{}/b/{}/o/{}?alt=media", base_url, req.bucket.escape(), req.object.escape());
    let builder = range.with_header(client.get(url).query(&req));
    if let Some(e) = &req.encryption {
        e.with_headers(builder)
    } else {
        builder
    }
}