diff --git a/crates/dbx-core/src/lib.rs b/crates/dbx-core/src/lib.rs index 859f270e87..e0608ab9bd 100644 --- a/crates/dbx-core/src/lib.rs +++ b/crates/dbx-core/src/lib.rs @@ -22,7 +22,9 @@ pub mod transfer; pub mod types; pub mod update; -pub const GITHUB_PROXIES: &[&str] = &["https://update.hwdns.net/", "https://gh-proxy.org/", ""]; +pub const R2_CDN_BASE: &str = "https://dl.dbxio.com/"; + +pub const GITHUB_PROXIES: &[&str] = &["https://gh-proxy.org/", ""]; pub async fn race_github_proxies( client: &reqwest::Client, @@ -57,3 +59,53 @@ pub async fn race_github_proxies( Err(last_err) => Err(last_err), } } + +pub async fn race_download( + client: &reqwest::Client, + github_url: &str, + r2_path: &str, + user_agent: &str, +) -> Result { + use futures::future::select_ok; + use std::pin::Pin; + + let mut futs: Vec> + Send>>> = + Vec::with_capacity(GITHUB_PROXIES.len() + 1); + + // R2 CDN source + { + let url = format!("{R2_CDN_BASE}{r2_path}"); + let client = client.clone(); + let ua = user_agent.to_string(); + futs.push(Box::pin(async move { + client + .get(&url) + .header(reqwest::header::USER_AGENT, ua) + .send() + .await + .and_then(|r| r.error_for_status()) + .map_err(|e| format!("{e}")) + })); + } + + // GitHub proxies + direct + for proxy in GITHUB_PROXIES { + let url = format!("{proxy}{github_url}"); + let client = client.clone(); + let ua = user_agent.to_string(); + futs.push(Box::pin(async move { + client + .get(&url) + .header(reqwest::header::USER_AGENT, ua) + .send() + .await + .and_then(|r| r.error_for_status()) + .map_err(|e| format!("{e}")) + }) as Pin> + Send>>); + } + + match select_ok(futs).await { + Ok((resp, _)) => Ok(resp), + Err(last_err) => Err(last_err), + } +}