Skip to content

Commit

Permalink
chore: use async reqwest
Browse files Browse the repository at this point in the history
  • Loading branch information
jdx committed May 23, 2024
1 parent ef24c46 commit dbae99d
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 46 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[*.toml]
indent_style = space
indent_size = 2
indent_size = 4

[{*.sh,.mise/tasks/**/*,e2e/**/*}]
indent_style = space
Expand Down
72 changes: 71 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,6 @@ regex = "1.10.4"
# mise error sending request for url (https://api.github.com/repos/jdx/mise/releases): error trying to connect: invalid URL, scheme is not http
# mise error trying to connect: invalid URL, scheme is not http
reqwest = { version = "<0.12", default-features = false, features = [
"blocking",
"json",
"gzip",
] }
Expand All @@ -114,6 +113,7 @@ tempfile = "3.10.1"
tera = { version = "1.19.1", default-features = false }
terminal_size = "0.3.0"
thiserror = "1.0.59"
tokio = { version = "1.37.0", features = ["full"] }
toml = { version = "0.8.12", features = ["parse"] }
toml_edit = { version = "0.22.12", features = ["parse"] }
url = "2.5.0"
Expand Down
91 changes: 48 additions & 43 deletions src/http.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use std::fs::File;
use std::io::{Read, Write};
use std::io::Write;
use std::path::Path;
use std::time::Duration;

use eyre::{Report, Result};
use once_cell::sync::Lazy;
use reqwest::blocking::{ClientBuilder, Response};
use reqwest::IntoUrl;
use reqwest::{ClientBuilder, Response};
use url::Url;

use crate::cli::version;
use crate::env::MISE_FETCH_REMOTE_VERSIONS_TIMEOUT;
Expand All @@ -25,7 +26,7 @@ pub static HTTP_FETCH: Lazy<Client> =

#[derive(Debug)]
pub struct Client {
reqwest: reqwest::blocking::Client,
reqwest: reqwest::Client,
}

impl Client {
Expand All @@ -44,40 +45,42 @@ impl Client {
.gzip(true)
}

pub fn get<U: IntoUrl>(&self, url: U) -> Result<Response> {
let mut url = url.into_url().unwrap();
debug!("GET {}", url);
let mut req = self.reqwest.get(url.clone());
if url.host_str() == Some("api.github.com") {
if let Some(token) = &*env::GITHUB_API_TOKEN {
req = req.header("authorization", format!("token {}", token));
async fn get<U: IntoUrl>(&self, url: U) -> Result<Response> {
let get = |url: Url| async move {
debug!("GET {}", &url);
let mut req = self.reqwest.get(url.clone());
if url.host_str() == Some("api.github.com") {
if let Some(token) = &*env::GITHUB_API_TOKEN {
req = req.header("authorization", format!("token {}", token));
}
}
}

let resp = match req.send() {
let resp = req.send().await?;
debug!("GET {url} {}", resp.status());
resp.error_for_status_ref()?;
Ok(resp)
};
let mut url = url.into_url().unwrap();
let resp = match get(url.clone()).await {
Ok(resp) => resp,
Err(_) if url.scheme() == "http" => {
// try with https since http may be blocked
url.set_scheme("https").unwrap();
return self.get(url);
get(url).await?
}
Err(err) => return Err(err.into()),
Err(err) => return Err(err),
};

debug!("GET {url} {}", resp.status());
if url.scheme() == "http" && resp.error_for_status_ref().is_err() {
// try with https since http may be blocked
url.set_scheme("https").unwrap();
return self.get(url);
}
resp.error_for_status_ref()?;
Ok(resp)
}

pub fn get_text<U: IntoUrl>(&self, url: U) -> Result<String> {
let mut url = url.into_url().unwrap();
let resp = self.get(url.clone())?;
let text = resp.text()?;
let rt = tokio::runtime::Runtime::new()?;
let text = rt.block_on(async {
let resp = self.get(url.clone()).await?;
Ok::<String, eyre::Error>(resp.text().await?)
})?;
if text.starts_with("<!DOCTYPE html>") {
if url.scheme() == "http" {
// try with https since http may be blocked
Expand All @@ -94,8 +97,11 @@ impl Client {
T: serde::de::DeserializeOwned,
{
let url = url.into_url().unwrap();
let resp = self.get(url)?;
let json = resp.json()?;
let rt = tokio::runtime::Runtime::new()?;
let json = rt.block_on(async {
let resp = self.get(url).await?;
Ok::<T, eyre::Error>(resp.json().await?)
})?;
Ok(json)
}

Expand All @@ -107,27 +113,26 @@ impl Client {
) -> Result<()> {
let url = url.into_url()?;
debug!("GET Downloading {} to {}", &url, display_path(path));
let mut resp = self.get(url)?;
if let Some(length) = resp.content_length() {
if let Some(pr) = pr {
pr.set_length(length);
}
}

file::create_dir_all(path.parent().unwrap())?;

let mut buf = [0; 32 * 1024];
let mut file = File::create(path)?;
loop {
let n = resp.read(&mut buf)?;
if n == 0 {
break;
let rt = tokio::runtime::Runtime::new()?;
rt.block_on(async {
let mut resp = self.get(url).await?;
if let Some(length) = resp.content_length() {
if let Some(pr) = pr {
pr.set_length(length);
}
}
file.write_all(&buf[..n])?;
if let Some(pr) = pr {
pr.inc(n as u64);

file::create_dir_all(path.parent().unwrap())?;
let mut file = File::create(path)?;
while let Some(chunk) = resp.chunk().await? {
file.write_all(&chunk)?;
if let Some(pr) = pr {
pr.inc(chunk.len() as u64);
}
}
}
Ok::<(), eyre::Error>(())
})?;
Ok(())
}
}
Expand Down

0 comments on commit dbae99d

Please sign in to comment.