From 13073abf4c1158942151679533006b7cfefe9e4d Mon Sep 17 00:00:00 2001 From: Teakowa <27560638+Teakowa@users.noreply.github.com> Date: Wed, 9 Sep 2026 02:56:45 +0800 Subject: [PATCH 1/3] fix(provider): use HTTP/2 release client Closes #288 --- Cargo.lock | 289 ++++++++++++++++++++++- Cargo.toml | 1 + crates/wright-driver/Cargo.toml | 1 + crates/wright-driver/src/opy_provider.rs | 58 +++-- 4 files changed, 318 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a516b82..deda124 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,6 +206,23 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "cfg_aliases" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" + +[[package]] +name = "chacha20" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.1", + "rand_core", +] + [[package]] name = "clang-sys" version = "1.9.1" @@ -302,6 +319,16 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -317,6 +344,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -459,6 +495,12 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -569,8 +611,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 6.0.0", + "rand_core", + "wasm-bindgen", ] [[package]] @@ -579,6 +624,25 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" +[[package]] +name = "h2" +version = "0.4.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9f37a958b41b3b19ee2707c06439c0e9e547e847223eb791ecb0cb821c65e27" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.17.1" @@ -640,6 +704,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", + "h2", "http", "http-body", "httparse", @@ -650,6 +715,22 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-native-certs 0.8.4", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.20" @@ -945,6 +1026,12 @@ version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "lsp-types" version = "0.97.0" @@ -1112,6 +1199,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "opy-rs" version = "0.1.18" @@ -1203,6 +1296,62 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quinn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4bfc015262b9df63c8845072ce59068853ff5872180c2ce2f13038b970e560" +dependencies = [ + "bytes", + "getrandom 0.4.3", + "lru-slab", + "rand", + "rand_pcg", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a133f956daabe89a61a685c2649f13d82d5aa4bd5d12d1277e1072a21c0694" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.47" @@ -1224,6 +1373,32 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +dependencies = [ + "chacha20", + "getrandom 0.4.3", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + +[[package]] +name = "rand_pcg" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a" +dependencies = [ + "rand_core", +] + [[package]] name = "redox_syscall" version = "0.5.18" @@ -1273,20 +1448,27 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", + "rustls-native-certs 0.8.4", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -1350,11 +1532,23 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework", + "security-framework 2.11.1", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe 0.2.1", + "rustls-pki-types", + "schannel", + "security-framework 3.7.0", ] [[package]] @@ -1372,6 +1566,7 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" dependencies = [ + "web-time", "zeroize", ] @@ -1429,7 +1624,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.13.1", - "core-foundation", + "core-foundation 0.9.4", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.13.1", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", @@ -1527,7 +1735,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -1661,6 +1869,26 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + [[package]] name = "time" version = "0.3.45" @@ -1701,12 +1929,28 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb4ebadaa0af04fab11ae01eb5f9fdb5f9c5b875506e210e71c07873528baa7f" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ + "bytes", "libc", "mio", "pin-project-lite", @@ -1714,6 +1958,30 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "libc", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "1.1.4+spec-1.1.0" @@ -1852,7 +2120,7 @@ dependencies = [ "log", "once_cell", "rustls", - "rustls-native-certs", + "rustls-native-certs 0.7.3", "rustls-pki-types", "url", "webpki-roots 0.26.11", @@ -1997,6 +2265,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.26.11" @@ -2198,6 +2476,7 @@ name = "wright-driver" version = "0.2.19" dependencies = [ "flate2", + "reqwest", "serde", "serde_json", "sha2", diff --git a/Cargo.toml b/Cargo.toml index 7f84cba..2c169fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ sha2 = "0.10" flate2 = "1" tar = "0.4" ureq = { version = "2", features = ["native-certs"] } +reqwest = { version = "0.12", default-features = false, features = ["blocking", "http2", "rustls-tls-native-roots"] } wright-analyzer = { path = "crates/wright-analyzer" } wright-core = { path = "crates/wright-core" } wright-driver = { path = "crates/wright-driver" } diff --git a/crates/wright-driver/Cargo.toml b/crates/wright-driver/Cargo.toml index fe2338a..1d4c60f 100644 --- a/crates/wright-driver/Cargo.toml +++ b/crates/wright-driver/Cargo.toml @@ -16,6 +16,7 @@ serde_json.workspace = true sha2.workspace = true flate2.workspace = true tar.workspace = true +reqwest.workspace = true ureq.workspace = true url = "2" wright-analyzer.workspace = true diff --git a/crates/wright-driver/src/opy_provider.rs b/crates/wright-driver/src/opy_provider.rs index 7052c4e..a6acc96 100644 --- a/crates/wright-driver/src/opy_provider.rs +++ b/crates/wright-driver/src/opy_provider.rs @@ -189,9 +189,11 @@ impl OpyProviderResolver { requested_version: Option<&str>, target: &str, ) -> Result { + let requested_version = requested_version.map(normalize_version).transpose()?; + let client = provider_client()?; let version = match requested_version { - Some(version) => normalize_version(version)?, - None => self.fetch_latest_version()?, + Some(version) => version, + None => self.fetch_latest_version(&client)?, }; let archive_name = format!("opy-provider-{version}-{target}.{PROVIDER_ARCHIVE_EXTENSION}"); let archive_url = format!( @@ -199,8 +201,8 @@ impl OpyProviderResolver { self.base_url.trim_end_matches('/') ); let checksum_url = format!("{archive_url}.sha256"); - let archive = fetch(&archive_url)?; - let checksum = fetch_text(&checksum_url)?; + let archive = fetch(&client, &archive_url)?; + let checksum = fetch_text(&client, &checksum_url)?; verify_checksum(&archive, &checksum, &archive_name)?; self.install_archive(&version, target, &archive)?; Ok(ResolvedOpyProvider { @@ -209,8 +211,11 @@ impl OpyProviderResolver { }) } - fn fetch_latest_version(&self) -> Result { - let body = fetch_text(&self.latest_version_url)?; + fn fetch_latest_version( + &self, + client: &reqwest::blocking::Client, + ) -> Result { + let body = fetch_text(client, &self.latest_version_url)?; normalize_version(body.trim()) } @@ -473,30 +478,32 @@ fn is_executable(path: &Path) -> bool { } } -fn fetch_text(url: &str) -> Result { - let bytes = fetch(url)?; +fn provider_client() -> Result { + reqwest::blocking::Client::builder() + .user_agent(concat!("wright-opy-provider/", env!("CARGO_PKG_VERSION"))) + .timeout(Duration::from_secs(60)) + .build() + .map_err(|error| { + OpyProviderError::offline(format!( + "cannot initialize HTTPS client for OPY provider release source: {error}" + )) + }) +} + +fn fetch_text(client: &reqwest::blocking::Client, url: &str) -> Result { + let bytes = fetch(client, url)?; String::from_utf8(bytes).map_err(|error| { OpyProviderError::download(format!("cannot decode response from {url}: {error}")) }) } -fn fetch(url: &str) -> Result, OpyProviderError> { - let response = ureq::get(url) - .set( - "User-Agent", - concat!("wright-opy-provider/", env!("CARGO_PKG_VERSION")), - ) - .timeout(Duration::from_secs(60)) - .call() - .map_err(|error| match error { - ureq::Error::Status(status, _) => { - OpyProviderError::download(format!("GET {url} failed with HTTP {status}")) - } - ureq::Error::Transport(error) => OpyProviderError::offline(format!( - "cannot reach OPY provider release source {url}: {error}" - )), - })?; - if !(200..300).contains(&response.status()) { +fn fetch(client: &reqwest::blocking::Client, url: &str) -> Result, OpyProviderError> { + let response = client.get(url).send().map_err(|error| { + OpyProviderError::offline(format!( + "cannot reach OPY provider release source {url}: {error}" + )) + })?; + if !response.status().is_success() { return Err(OpyProviderError::download(format!( "GET {url} failed with HTTP {}", response.status() @@ -504,7 +511,6 @@ fn fetch(url: &str) -> Result, OpyProviderError> { } let mut bytes = Vec::new(); response - .into_reader() .take(MAX_DOWNLOAD_BYTES + 1) .read_to_end(&mut bytes) .map_err(|error| { From 0559d6aa6a48dc8fa83422ce51b967332184b1ec Mon Sep 17 00:00:00 2001 From: Teakowa <27560638+Teakowa@users.noreply.github.com> Date: Wed, 9 Sep 2026 03:06:18 +0800 Subject: [PATCH 2/3] fix(update): migrate self-update HTTP client Refs #288 --- Cargo.lock | 100 ++------------------------------ Cargo.toml | 1 - crates/wright-cli/Cargo.toml | 2 +- crates/wright-cli/src/update.rs | 51 +++++++++++----- crates/wright-driver/Cargo.toml | 1 - 5 files changed, 43 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index deda124..9a6ed5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -309,16 +309,6 @@ dependencies = [ "walkdir", ] -[[package]] -name = "core-foundation" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation" version = "0.10.1" @@ -725,7 +715,7 @@ dependencies = [ "hyper", "hyper-util", "rustls", - "rustls-native-certs 0.8.4", + "rustls-native-certs", "tokio", "tokio-rustls", "tower-service", @@ -1193,12 +1183,6 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" -[[package]] -name = "openssl-probe" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - [[package]] name = "openssl-probe" version = "0.2.1" @@ -1461,7 +1445,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs 0.8.4", + "rustls-native-certs", "rustls-pki-types", "serde", "serde_json", @@ -1517,7 +1501,6 @@ version = "0.23.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0283386ce02abc0151e1761d08802dfe86c173b0b494af5cbc086574e453da06" dependencies = [ - "log", "once_cell", "ring", "rustls-pki-types", @@ -1526,38 +1509,16 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-native-certs" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" -dependencies = [ - "openssl-probe 0.1.6", - "rustls-pemfile", - "rustls-pki-types", - "schannel", - "security-framework 2.11.1", -] - [[package]] name = "rustls-native-certs" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ - "openssl-probe 0.2.1", + "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.7.0", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", + "security-framework", ] [[package]] @@ -1617,19 +1578,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.13.1", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - [[package]] name = "security-framework" version = "3.7.0" @@ -1637,7 +1585,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.13.1", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -2109,23 +2057,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "2.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d" -dependencies = [ - "base64", - "flate2", - "log", - "once_cell", - "rustls", - "rustls-native-certs 0.7.3", - "rustls-pki-types", - "url", - "webpki-roots 0.26.11", -] - [[package]] name = "url" version = "2.5.8" @@ -2275,24 +2206,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webpki-roots" -version = "0.26.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" -dependencies = [ - "webpki-roots 1.0.9", -] - -[[package]] -name = "webpki-roots" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a" -dependencies = [ - "rustls-pki-types", -] - [[package]] name = "winapi-util" version = "0.1.11" @@ -2443,11 +2356,11 @@ dependencies = [ "flate2", "insta", "jsonschema", + "reqwest", "serde", "serde_json", "sha2", "tar", - "ureq", "workshop-rs", "wright-analyzer", "wright-driver", @@ -2481,7 +2394,6 @@ dependencies = [ "serde_json", "sha2", "tar", - "ureq", "url", "workshop-rs", "wright-analyzer", diff --git a/Cargo.toml b/Cargo.toml index 2c169fa..2b49c64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ serde_json = "1" sha2 = "0.10" flate2 = "1" tar = "0.4" -ureq = { version = "2", features = ["native-certs"] } reqwest = { version = "0.12", default-features = false, features = ["blocking", "http2", "rustls-tls-native-roots"] } wright-analyzer = { path = "crates/wright-analyzer" } wright-core = { path = "crates/wright-core" } diff --git a/crates/wright-cli/Cargo.toml b/crates/wright-cli/Cargo.toml index af22acf..942c648 100644 --- a/crates/wright-cli/Cargo.toml +++ b/crates/wright-cli/Cargo.toml @@ -22,7 +22,7 @@ serde = { workspace = true, features = ["derive"] } serde_json.workspace = true sha2.workspace = true tar = "0.4" -ureq = "2" +reqwest.workspace = true wright-driver.workspace = true [dev-dependencies] diff --git a/crates/wright-cli/src/update.rs b/crates/wright-cli/src/update.rs index 6a92b28..3c781c7 100644 --- a/crates/wright-cli/src/update.rs +++ b/crates/wright-cli/src/update.rs @@ -167,13 +167,14 @@ pub(crate) fn run(check_only: bool, requested: Option<&str>) -> Result { parse_version(version)?; version.trim_start_matches('v').to_string() } - None => resolve_latest(&env_api_url())?, + None => resolve_latest(&client, &env_api_url())?, }; match compare_versions(¤t, &target_version) { @@ -203,7 +204,13 @@ pub(crate) fn run(check_only: bool, requested: Option<&str>) -> Result installing wright {current} -> {target_version}"); - install_version(&target_version, platform, &env_base_url(), install_dir)?; + install_version( + &client, + &target_version, + platform, + &env_base_url(), + install_dir, + )?; Ok(exit::SUCCESS) } @@ -276,8 +283,11 @@ fn detect_provenance(exe: &Path) -> Provenance { } /// Resolve the latest stable release version from the GitHub Releases API. -fn resolve_latest(api_url: &str) -> Result { - let body = fetch_text(api_url)?; +fn resolve_latest( + client: &reqwest::blocking::Client, + api_url: &str, +) -> Result { + let body = fetch_text(client, api_url)?; let value: serde_json::Value = serde_json::from_str(&body).map_err(|error| { UpdateError::failed(format!( "could not parse the latest-release response from {api_url}: {error}" @@ -298,6 +308,7 @@ fn resolve_latest(api_url: &str) -> Result { /// Download, verify, extract, and atomically install the release archive. fn install_version( + client: &reqwest::blocking::Client, version: &str, platform: Platform, base_url: &str, @@ -308,8 +319,8 @@ fn install_version( let checksum_url = format!("{archive_url}.sha256"); println!("==> downloading {archive_url}"); - let archive = fetch(&archive_url)?; - let checksum = fetch_text(&checksum_url)?; + let archive = fetch(client, &archive_url)?; + let checksum = fetch_text(client, &checksum_url)?; println!("==> verifying SHA-256 checksum"); verify_checksum(&archive, &checksum, &archive_name)?; @@ -486,25 +497,36 @@ fn check_version(exe: &Path, version: &str) -> Result<(), UpdateError> { } /// Fetch `url` and return the response body as UTF-8 text. -fn fetch_text(url: &str) -> Result { - let bytes = fetch(url)?; +fn update_client() -> Result { + reqwest::blocking::Client::builder() + .user_agent(USER_AGENT) + .timeout(Duration::from_secs(60)) + .build() + .map_err(|error| { + UpdateError::failed(format!( + "could not initialize HTTPS client for release downloads: {error}" + )) + }) +} + +fn fetch_text(client: &reqwest::blocking::Client, url: &str) -> Result { + let bytes = fetch(client, url)?; String::from_utf8(bytes).map_err(|error| { UpdateError::failed(format!("could not decode the response from {url}: {error}")) }) } /// Fetch `url` and return the raw response body (bounded to 128 MiB). -fn fetch(url: &str) -> Result, UpdateError> { - let response = ureq::get(url) - .set("User-Agent", USER_AGENT) - .timeout(Duration::from_secs(60)) - .call() +fn fetch(client: &reqwest::blocking::Client, url: &str) -> Result, UpdateError> { + let response = client + .get(url) + .send() .map_err(|error| { UpdateError::failed(format!( "could not download {url} ({error}); check the network connection or pin a version with `wright update --version`" )) })?; - if !(200..300).contains(&response.status()) { + if !response.status().is_success() { return Err(UpdateError::failed(format!( "could not download {url} (HTTP {})", response.status() @@ -512,7 +534,6 @@ fn fetch(url: &str) -> Result, UpdateError> { } let mut bytes = Vec::new(); response - .into_reader() .take(128 * 1024 * 1024) .read_to_end(&mut bytes) .map_err(|error| UpdateError::failed(format!("could not download {url}: {error}")))?; diff --git a/crates/wright-driver/Cargo.toml b/crates/wright-driver/Cargo.toml index 1d4c60f..fc42430 100644 --- a/crates/wright-driver/Cargo.toml +++ b/crates/wright-driver/Cargo.toml @@ -17,7 +17,6 @@ sha2.workspace = true flate2.workspace = true tar.workspace = true reqwest.workspace = true -ureq.workspace = true url = "2" wright-analyzer.workspace = true wright-core.workspace = true From 3d4a462588dbb5702dd015ff6717c658f5d297a5 Mon Sep 17 00:00:00 2001 From: Teakowa <27560638+Teakowa@users.noreply.github.com> Date: Wed, 9 Sep 2026 03:14:34 +0800 Subject: [PATCH 3/3] fix(update): defer release client construction Refs #288 --- crates/wright-cli/src/update.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/crates/wright-cli/src/update.rs b/crates/wright-cli/src/update.rs index 3c781c7..d2019b3 100644 --- a/crates/wright-cli/src/update.rs +++ b/crates/wright-cli/src/update.rs @@ -167,14 +167,17 @@ pub(crate) fn run(check_only: bool, requested: Option<&str>) -> Result { parse_version(version)?; - version.trim_start_matches('v').to_string() + (version.trim_start_matches('v').to_string(), None) + } + None => { + let client = update_client()?; + let version = resolve_latest(&client, &env_api_url())?; + (version, Some(client)) } - None => resolve_latest(&client, &env_api_url())?, }; match compare_versions(¤t, &target_version) { @@ -204,6 +207,10 @@ pub(crate) fn run(check_only: bool, requested: Option<&str>) -> Result installing wright {current} -> {target_version}"); + let client = match client { + Some(client) => client, + None => update_client()?, + }; install_version( &client, &target_version,