commit 21406a80688851194f2659c5bc0ae1cf00c7f906
parent 570f44de7f09b6e6228717fbde3434130eb2da18
Author: egor-achkasov <eaachkasov@gmail.com>
Date: Wed, 6 May 2026 15:49:22 +0000
Replace reqwest with ureq
Diffstat:
3 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -24,5 +24,5 @@ anyhow = "1.0.102"
arboard = "3"
clap = { version = "4.5.57", features = ["derive"] }
ratatui = "0.29"
-reqwest = { version = "0.12", features = ["blocking"] }
scraper = "0.25.0"
+ureq = "3.3.0"
diff --git a/src/lib/download.rs b/src/lib/download.rs
@@ -1,25 +1,24 @@
-use anyhow::{anyhow, Result};
-
-/// Downloads a URL, retrying up to `tries` times.
-///
-/// # Errors
-/// Returns an error if all attempts fail or `tries` is 0.
-pub fn download(url: &str, tries: u32) -> Result<reqwest::blocking::Response> {
- static CLIENT: std::sync::LazyLock<reqwest::blocking::Client> =
- std::sync::LazyLock::new(reqwest::blocking::Client::new);
-
- for attempt in 0..tries {
- if attempt > 0 {
- std::thread::sleep(std::time::Duration::from_millis(500 * 2u64.pow(attempt)));
- }
- let response = CLIENT.get(url).send()?;
- if response.status().is_success() {
- return Ok(response);
- }
- if response.status().is_client_error() {
- return Err(anyhow!("client error: {}", response.status()));
- }
- }
-
- Err(anyhow!("failed to download {} after {} tries", url, tries))
-}
+use anyhow::{anyhow, Result};
+
+/// Downloads a URL, retrying up to `tries` times.
+///
+/// # Errors
+/// Returns an error if all attempts fail or `tries` is 0.
+pub fn download(url: &str, tries: u32) -> Result<ureq::http::Response<ureq::Body>> {
+ static CLIENT: std::sync::LazyLock<ureq::Agent> =
+ std::sync::LazyLock::new(ureq::Agent::new_with_defaults);
+ for attempt in 0..tries {
+ if attempt > 0 {
+ std::thread::sleep(std::time::Duration::from_millis(500 * 2u64.pow(attempt)));
+ }
+ match CLIENT.get(url).call() {
+ Ok(response) => return Ok(response),
+ Err(ureq::Error::StatusCode(code)) if code >= 400 && code < 500 => {
+ return Err(anyhow!("client error: {}", code));
+ }
+ Err(ureq::Error::StatusCode(_)) => continue,
+ Err(e) => return Err(e.into()),
+ }
+ }
+ Err(anyhow!("failed to download {} after {} tries", url, tries))
+}
diff --git a/src/lib/lib.rs b/src/lib/lib.rs
@@ -16,7 +16,10 @@ pub const BASE_URL: &str = "https://arhivach.vc";
pub fn run(config: &config::Config, tx: Sender<event::Event>) -> Result<()> {
tx.send(event::Event::GetStarted)?;
- let html = download::download(&config.url, config.download_retries)?.text()?;
+ let html = download::download(&config.url, config.download_retries)?
+ .body_mut()
+ .read_to_string()
+ .context("failed to read response body")?;
let posts = Post::parse_posts(&html)
.inspect_err(|e| { let _ = tx.send(event::Event::GetFailed { error: format!("{:#}", e) }); })
.context("failed to parse posts")?;
@@ -43,8 +46,8 @@ fn run_download(posts: &[Post], config: &config::Config, tx: Sender<event::Event
let download_item = |url: &str, filepath: &std::path::PathBuf| -> Result<()> {
let result = download::download(url, config.download_retries)?;
- anyhow::ensure!(result.status().is_success(), "failed to download {}: {}", url, result.status());
- let bytes = result.bytes()?;
+ let mut bytes = Vec::new();
+ std::io::Read::read_to_end(&mut result.into_body().as_reader(), &mut bytes)?;
anyhow::ensure!(!bytes.is_empty(), "empty file: {}", url);
std::fs::write(filepath, bytes)?;
Ok(())