Replace reqwest with ureq (#417)

ureq is a blocking HTTP client. ureq is simpler than reqwest. This
brings:
- smaller binary size
- cleaner configuration interfaces
This commit is contained in:
Erick Guan 2025-03-09 22:06:47 +01:00 committed by GitHub
commit 3d8d488f66
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 188 additions and 1017 deletions

1093
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -25,9 +25,9 @@ app_dirs = { version = "2", package = "app_dirs2" }
clap = { version = "4", features = ["std", "derive", "help", "usage", "cargo", "error-context", "color", "wrap_help"], default-features = false }
env_logger = { version = "0.11", optional = true }
log = "0.4"
reqwest = { version = "0.12.9", features = ["blocking"], default-features = false }
serde = "1.0.21"
serde_derive = "1.0.21"
ureq = { version = "3.0.8", default-features = false, features = ["gzip"] }
toml = "0.8.19"
walkdir = "2.0.1"
yansi = "1"
@ -47,20 +47,10 @@ filetime = "0.2.10"
default = ["native-tls", "rustls-with-webpki-roots", "rustls-with-native-roots"]
logging = ["env_logger"]
# Reqwest (the HTTP client library) can handle TLS connections in four
# different modes:
#
# - Rustls with:
# - native roots
# - WebPK roots
# - Native TLS (SChannel on Windows, Secure Transport on macOS and OpenSSL otherwise) with:
# - native roots
# - WebPK roots (not implemented in tealdeer)
#
# At least one of variants must be selected. By default, uses native TLS and native roots.
native-tls = ["reqwest/rustls-tls-native-roots-no-provider", "reqwest/rustls-tls-webpki-roots-no-provider", "reqwest/native-tls"]
rustls-with-webpki-roots = ["reqwest/rustls-tls-native-roots-no-provider", "reqwest/rustls-tls-webpki-roots"]
rustls-with-native-roots = ["reqwest/rustls-tls-webpki-roots-no-provider", "reqwest/rustls-tls-native-roots"]
# At least one of variants for `ureq` HTTP client must be selected.
native-tls = ["ureq/native-tls", "ureq/platform-verifier"]
rustls-with-webpki-roots = ["ureq/rustls"] # ureq uses WebPKI roots by default
rustls-with-native-roots = ["ureq/rustls", "ureq/platform-verifier"]
ignore-online-tests = []

View file

@ -1,5 +1,4 @@
use std::{
env,
ffi::OsStr,
fs::{self, File},
io::{BufReader, Cursor, Read},
@ -9,7 +8,8 @@ use std::{
use anyhow::{ensure, Context, Result};
use log::debug;
use reqwest::{blocking::Client, Proxy};
use ureq::tls::{RootCerts, TlsConfig, TlsProvider};
use ureq::Agent;
use walkdir::{DirEntry, WalkDir};
use zip::ZipArchive;
@ -137,54 +137,6 @@ impl Cache {
self.cache_dir.join(TLDR_PAGES_DIR)
}
fn build_client(tls_backend: TlsBackend) -> Result<Client> {
let mut builder = Client::builder();
builder = match tls_backend {
#[cfg(feature = "native-tls")]
TlsBackend::NativeTls => builder
.use_native_tls()
.tls_built_in_root_certs(true)
.tls_built_in_webpki_certs(false)
.tls_built_in_native_certs(false),
#[cfg(feature = "rustls-with-webpki-roots")]
TlsBackend::RustlsWithWebpkiRoots => builder
.use_rustls_tls()
.tls_built_in_root_certs(false)
.tls_built_in_webpki_certs(true)
.tls_built_in_native_certs(false),
#[cfg(feature = "rustls-with-native-roots")]
TlsBackend::RustlsWithNativeRoots => builder
.use_rustls_tls()
.tls_built_in_root_certs(false)
.tls_built_in_webpki_certs(false)
.tls_built_in_native_certs(true),
};
if let Ok(ref host) = env::var("HTTP_PROXY") {
if let Ok(proxy) = Proxy::http(host) {
builder = builder.proxy(proxy);
}
}
if let Ok(ref host) = env::var("HTTPS_PROXY") {
if let Ok(proxy) = Proxy::https(host) {
builder = builder.proxy(proxy);
}
}
builder.build().context("Could not instantiate HTTP client")
}
/// Download the archive from the specified URL.
fn download(client: &Client, archive_url: &str) -> Result<Vec<u8>> {
let mut resp = client
.get(archive_url)
.send()?
.error_for_status()
.with_context(|| format!("Could not download tldr pages from {archive_url}"))?;
let mut buf: Vec<u8> = vec![];
let bytes_downloaded = resp.copy_to(&mut buf)?;
debug!("{} bytes downloaded", bytes_downloaded);
Ok(buf)
}
/// Update the pages cache from the specified URL.
pub fn update(&self, archive_source: &str) -> Result<()> {
self.ensure_cache_dir_exists()?;
@ -475,6 +427,42 @@ impl Cache {
}
}
impl Cache {
fn build_client(tls_backend: TlsBackend) -> Result<Agent> {
let tls_builder = match tls_backend {
#[cfg(feature = "native-tls")]
TlsBackend::NativeTls => TlsConfig::builder()
.provider(TlsProvider::NativeTls)
.root_certs(RootCerts::PlatformVerifier),
#[cfg(feature = "rustls-with-webpki-roots")]
TlsBackend::RustlsWithWebpkiRoots => TlsConfig::builder()
.provider(TlsProvider::Rustls)
.root_certs(RootCerts::WebPki),
#[cfg(feature = "rustls-with-native-roots")]
TlsBackend::RustlsWithNativeRoots => TlsConfig::builder()
.provider(TlsProvider::Rustls)
.root_certs(RootCerts::PlatformVerifier),
};
let config = Agent::config_builder()
.tls_config(tls_builder.build())
.build();
Ok(config.into())
}
/// Download the archive from the specified URL.
fn download(client: &Agent, archive_url: &str) -> Result<Vec<u8>> {
let response = client
.get(archive_url)
.call()
.with_context(|| format!("Could not download tldr pages from {archive_url}"))?;
let mut buf: Vec<u8> = Vec::new();
response.into_body().into_reader().read_to_end(&mut buf)?;
debug!("{} bytes downloaded", buf.len());
Ok(buf)
}
}
/// Unit Tests for cache module
#[cfg(test)]
mod tests {