Skip to main content

fast_down/utils/
puller.rs

1use crate::{
2    FileId, ProgressEntry, PullResult, PullStream,
3    http::{HttpError, HttpPuller},
4};
5use fast_pull::Puller;
6use parking_lot::Mutex;
7use reqwest::{Client, ClientBuilder, Proxy, Response, header::HeaderMap};
8use std::sync::Arc;
9use url::Url;
10
11pub fn build_client(
12    headers: &HeaderMap,
13    proxy: &str,
14    accept_invalid_certs: bool,
15    accept_invalid_hostnames: bool,
16) -> Result<reqwest::Client, reqwest::Error> {
17    let mut client = ClientBuilder::new()
18        .default_headers(headers.clone())
19        .danger_accept_invalid_certs(accept_invalid_certs)
20        .danger_accept_invalid_hostnames(accept_invalid_hostnames);
21    if !proxy.is_empty() {
22        client = client.proxy(Proxy::all(proxy)?);
23    }
24    let client = client.build()?;
25    Ok(client)
26}
27
28#[derive(Debug)]
29pub struct FastDownPuller {
30    inner: HttpPuller<Client>,
31    headers: Arc<HeaderMap>,
32    proxy: Arc<str>,
33    url: Arc<Url>,
34    multiplexing: bool,
35    accept_invalid_certs: bool,
36    accept_invalid_hostnames: bool,
37    file_id: FileId,
38    resp: Option<Arc<Mutex<Option<Response>>>>,
39}
40
41pub struct FastDownPullerOptions<'a> {
42    pub url: Url,
43    pub headers: Arc<HeaderMap>,
44    pub proxy: &'a str,
45    pub multiplexing: bool,
46    pub accept_invalid_certs: bool,
47    pub accept_invalid_hostnames: bool,
48    pub file_id: FileId,
49    pub resp: Option<Arc<Mutex<Option<Response>>>>,
50}
51
52impl FastDownPuller {
53    pub fn new(option: FastDownPullerOptions) -> Result<Self, reqwest::Error> {
54        let client = build_client(
55            &option.headers,
56            option.proxy,
57            option.accept_invalid_certs,
58            option.accept_invalid_hostnames,
59        )?;
60        Ok(Self {
61            inner: HttpPuller::new(
62                option.url.clone(),
63                client,
64                option.resp.clone(),
65                option.file_id.clone(),
66            ),
67            resp: option.resp,
68            headers: option.headers,
69            proxy: Arc::from(option.proxy),
70            url: Arc::new(option.url),
71            multiplexing: option.multiplexing,
72            accept_invalid_certs: option.accept_invalid_certs,
73            accept_invalid_hostnames: option.accept_invalid_hostnames,
74            file_id: option.file_id,
75        })
76    }
77}
78
79impl Clone for FastDownPuller {
80    fn clone(&self) -> Self {
81        Self {
82            inner: if !self.multiplexing
83                && let Ok(client) = build_client(
84                    &self.headers,
85                    &self.proxy,
86                    self.accept_invalid_certs,
87                    self.accept_invalid_hostnames,
88                ) {
89                HttpPuller::new(
90                    self.url.as_ref().clone(),
91                    client,
92                    self.resp.clone(),
93                    self.file_id.clone(),
94                )
95            } else {
96                self.inner.clone()
97            },
98            resp: self.resp.clone(),
99            headers: self.headers.clone(),
100            proxy: self.proxy.clone(),
101            url: self.url.clone(),
102            multiplexing: self.multiplexing,
103            accept_invalid_certs: self.accept_invalid_certs,
104            accept_invalid_hostnames: self.accept_invalid_hostnames,
105            file_id: self.file_id.clone(),
106        }
107    }
108}
109
110impl Puller for FastDownPuller {
111    type Error = HttpError<Client>;
112    async fn pull(
113        &mut self,
114        range: Option<&ProgressEntry>,
115    ) -> PullResult<impl PullStream<Self::Error>, Self::Error> {
116        Puller::pull(&mut self.inner, range).await
117    }
118}