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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
use crate::progress::Progress;
use std::io::Write;
use hyper::body::HttpBody;
use crate::dns::SocketAddrs;
use http::response::Parts;

type Error = Box<dyn std::error::Error + Send + Sync>;

pub struct Downloader {
  request: Option<http::request::Builder>,
  https_only: bool,
  progress: Option<Box<dyn Progress>>,
  sockets: Option<SocketAddrs>
}

impl Downloader {
  pub fn new() -> Self {
    Self {
      request: Some(http::Request::builder()),
      https_only: true,
      progress: None,
      sockets: None
    }
  }

  pub fn use_uri(&mut self, uri: http::Uri) -> &mut Self {
    if let Some(host) = uri.host() {
      let builder = self.request.take().expect("Failed to take request-builder");
      self.request = Some(builder.uri(uri.clone())
                                 .header("host", host));
    } else {
      log::error!("URI {} is not a valid URI", &uri);
    }
    self
  }

  pub fn headers(&mut self) -> Option<&mut http::HeaderMap<http::HeaderValue>> {
    self.request.as_mut().map(|x| x.headers_mut()).flatten()
  }

  pub fn use_sockets(&mut self, sockets: SocketAddrs) -> &mut Self {
    self.sockets = Some(sockets);
    self
  }

  pub fn allow_http(&mut self) -> &mut Self {
    self.https_only = false;
    self
  }

  pub fn use_progress<T: Progress + 'static>(&mut self, progress: T) -> &mut Self {
    self.progress = Some(Box::new(progress));
    self
  }

  pub async fn download<T: HttpBody + Send + 'static>(mut self, body: T, to: &mut impl Write) -> Result<Parts, Error>  where T::Data: Send, T::Error: Into<Error> {
    crate::download::download(self.request.take().expect("Failed to take request-builder").body(body)?, to, self.https_only, &mut self.progress, self.sockets).await
  }
}