summaryrefslogtreecommitdiff
path: root/cli/http_util.rs
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2022-12-13 02:52:10 +0100
committerGitHub <noreply@github.com>2022-12-12 20:52:10 -0500
commit8c026dab92b20fea44bc66f84db48b885c7264d1 (patch)
tree884704fb4721c9e227859451e58f524ace0a2261 /cli/http_util.rs
parent4a17c930882c5765e5fdedb50b6493469f61e32d (diff)
feat: improve download progress bar (#16984)
Co-authored-by: David Sherret <dsherret@gmail.com>
Diffstat (limited to 'cli/http_util.rs')
-rw-r--r--cli/http_util.rs41
1 files changed, 41 insertions, 0 deletions
diff --git a/cli/http_util.rs b/cli/http_util.rs
index 827cc75f5..744493ceb 100644
--- a/cli/http_util.rs
+++ b/cli/http_util.rs
@@ -1,13 +1,16 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use crate::auth_tokens::AuthToken;
+use crate::util::progress_bar::UpdateGuard;
use crate::version::get_user_agent;
use cache_control::Cachability;
use cache_control::CacheControl;
use chrono::DateTime;
+use deno_core::anyhow::bail;
use deno_core::error::custom_error;
use deno_core::error::generic_error;
use deno_core::error::AnyError;
+use deno_core::futures::StreamExt;
use deno_core::url::Url;
use deno_runtime::deno_fetch::create_http_client;
use deno_runtime::deno_fetch::reqwest;
@@ -243,6 +246,44 @@ impl HttpClient {
self.0.get(url)
}
+ pub async fn download_with_progress<U: reqwest::IntoUrl>(
+ &self,
+ url: U,
+ progress_guard: &UpdateGuard,
+ ) -> Result<Option<Vec<u8>>, AnyError> {
+ let response = self.get(url).send().await?;
+
+ if response.status() == 404 {
+ Ok(None)
+ } else if !response.status().is_success() {
+ let status = response.status();
+ let maybe_response_text = response.text().await.ok();
+ bail!(
+ "Bad response: {:?}{}",
+ status,
+ match maybe_response_text {
+ Some(text) => format!("\n\n{}", text),
+ None => String::new(),
+ }
+ );
+ } else if let Some(total_size) = response.content_length() {
+ progress_guard.set_total_size(total_size);
+ let mut current_size = 0;
+ let mut data = Vec::with_capacity(total_size as usize);
+ let mut stream = response.bytes_stream();
+ while let Some(item) = stream.next().await {
+ let bytes = item?;
+ current_size += bytes.len() as u64;
+ progress_guard.set_position(current_size);
+ data.extend(bytes.into_iter());
+ }
+ Ok(Some(data))
+ } else {
+ let bytes = response.bytes().await?;
+ Ok(Some(bytes.into()))
+ }
+ }
+
/// Asynchronously fetches the given HTTP URL one pass only.
/// If no redirect is present and no error occurs,
/// yields Code(ResultPayload).