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
60
use crate::progress::Progress;
use crate::dns::ResolverService;
use crate::error::StatusError;
use std::io::Write;
use hyper::client::Client;
use hyper::body::HttpBody;
use hyper::client::HttpConnector;
use hyper_tls::HttpsConnector;
use crate::dns::SocketAddrs;
use http::response::Parts;
type Request<T> = crate::http::Request<T>;
type Error = Box<dyn std::error::Error + Send + Sync>;
pub async fn download<T: HttpBody + Send + 'static>(request: Request<T>, to: &mut impl Write, https_only: bool, progress: &mut Option<Box<dyn Progress>>, socket_addrs: Option<SocketAddrs>) -> Result<Parts, Error> where T::Data: Send, T::Error: Into<Error> {
let res;
if let Some(socket_addrs) = socket_addrs {
let resolver_service = ResolverService::new(socket_addrs.into());
let mut http_connector : HttpConnector<ResolverService> = HttpConnector::new_with_resolver(resolver_service);
http_connector.enforce_http(https_only);
let mut https_connector = HttpsConnector::new_with_connector(http_connector);
https_connector.https_only(https_only);
let client = Client::builder().build::<_, T>(https_connector);
res = client.request(request).await?;
} else {
let mut https_connector = HttpsConnector::new();
https_connector.https_only(https_only);
let client = Client::builder().build::<_, T>(https_connector);
res = client.request(request).await?;
}
let status = res.status();
let (parts, mut body) = res.into_parts();
if status == 200 || status == 206 {
if progress.is_some() {
if let Some(content_length) = parts.headers.get("content-length") {
let content_length : usize = content_length.to_str().expect("Couldn't convert content-length value to str.").parse().expect("Couldn't parse content-length as a usize.");
progress.as_deref_mut().map(|progress| progress.set_file_size(content_length)).unwrap().await;
}
}
while !body.is_end_stream() {
if let Some(chunk) = body.data().await {
let chunk = chunk?;
progress.as_deref_mut().map(|progress| progress.add_to_progress(chunk.len())).unwrap().await;
to.write_all(&chunk)?;
}
}
Ok::<Parts, Error>(parts)
} else {
Err::<Parts, Error>(StatusError::from(status))
}
}