|
|
|
@ -17,7 +17,7 @@ use http::{ |
|
|
|
Uri,
|
|
|
|
};
|
|
|
|
use http_body_util::BodyDataStream;
|
|
|
|
use log::debug;
|
|
|
|
use log::{debug, error};
|
|
|
|
use reqwest::{redirect::Policy, Body};
|
|
|
|
use tokio::{fs::File, io::AsyncWriteExt as _, time::timeout};
|
|
|
|
use tower::{util::BoxCloneService, ServiceBuilder, ServiceExt as _};
|
|
|
|
@ -47,6 +47,10 @@ pub(super) enum DownloadState { |
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub(super) struct Client {
|
|
|
|
buffer: usize,
|
|
|
|
rate_limit: u64,
|
|
|
|
concurrency_limit: usize,
|
|
|
|
timeout: Duration,
|
|
|
|
client: HttpClient,
|
|
|
|
default_headers: HeaderMap,
|
|
|
|
body_timeout: Option<Duration>,
|
|
|
|
@ -90,7 +94,43 @@ impl Client { |
|
|
|
HeaderValue::from_str(&( crate_name!().to_string() + "/"
|
|
|
|
+ crate_version!() )).unwrap() );
|
|
|
|
|
|
|
|
Ok(Self {client, default_headers, body_timeout})
|
|
|
|
Ok(Self { buffer
|
|
|
|
, rate_limit
|
|
|
|
, concurrency_limit
|
|
|
|
, timeout
|
|
|
|
, client
|
|
|
|
, default_headers
|
|
|
|
, body_timeout })
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_http_client( buffer: usize |
|
|
|
, rate_limit: u64 |
|
|
|
, concurrency_limit: usize |
|
|
|
, timeout: Duration ) -> Result<HttpClient, reqwest::Error> {
|
|
|
|
Ok( ServiceBuilder::new()
|
|
|
|
// Add some layers.
|
|
|
|
. buffer(buffer)
|
|
|
|
. rate_limit(rate_limit, Duration::from_secs(1))
|
|
|
|
. concurrency_limit(concurrency_limit)
|
|
|
|
. timeout(timeout)
|
|
|
|
. layer(DecompressionLayer::new())
|
|
|
|
// Make client compatible with the `tower-http` layers.
|
|
|
|
. layer(HttpClientLayer)
|
|
|
|
. service( reqwest::Client::builder()
|
|
|
|
. redirect(Policy::limited(5))
|
|
|
|
. build()? )
|
|
|
|
. map_err(anyhow::Error::msg)
|
|
|
|
. boxed_clone() )
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn rebuild_http_client(&mut self) {
|
|
|
|
match Self::build_http_client( self.buffer
|
|
|
|
, self.rate_limit
|
|
|
|
, self.concurrency_limit
|
|
|
|
, self.timeout ) {
|
|
|
|
Ok(client) => self.client = client,
|
|
|
|
Err(e) => error!("unable to re-create client: {}", e),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(super) fn set_body_timeout(mut self, timeout: Option<Duration>) -> Self {
|
|
|
|
|