From 40bb49fc0b80d5ff97875903b2c2e55ff394cecc Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sat, 27 Jun 2026 20:19:56 +0900 Subject: refactor(http): present reqwest instead of faking curl_version - StreamContextFactory: User-Agent reports the HTTP stack as "reqwest" - RequestProxy::supports_secure_proxy: always true (reqwest+rustls can always TLS to a proxy); drop the now-dead curl<7.52 guard in get_curl_options - DiagnoseCommand::get_curl_version: phase-D TODO placeholder Empirically verified: reqwest sends no default User-Agent (shirabe sets it explicitly) and accepts https:// proxy URLs. init+install output stays byte-identical to Composer. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/shirabe/src/command/diagnose_command.rs | 64 ++-------------------- crates/shirabe/src/util/http/request_proxy.rs | 33 +++-------- crates/shirabe/src/util/stream_context_factory.rs | 16 ++---- .../shirabe/tests/command/search_command_test.rs | 2 +- 4 files changed, 21 insertions(+), 94 deletions(-) (limited to 'crates/shirabe') diff --git a/crates/shirabe/src/command/diagnose_command.rs b/crates/shirabe/src/command/diagnose_command.rs index 68aec20..0bdf8ef 100644 --- a/crates/shirabe/src/command/diagnose_command.rs +++ b/crates/shirabe/src/command/diagnose_command.rs @@ -10,9 +10,8 @@ use shirabe_external_packages::symfony::console::input::InputInterface; use shirabe_external_packages::symfony::console::output::OutputInterface; use shirabe_external_packages::symfony::process::ExecutableFinder; use shirabe_php_shim::{ - CURL_VERSION_HTTP2, CURL_VERSION_HTTP3, CURL_VERSION_ZSTD, INFO_GENERAL, - InvalidArgumentException, OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, PHP_BINARY, PHP_EOL, - PHP_VERSION, PHP_VERSION_ID, PHP_WINDOWS_VERSION_BUILD, PhpMixed, curl_version, defined, + INFO_GENERAL, InvalidArgumentException, OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT, + PHP_BINARY, PHP_EOL, PHP_VERSION, PHP_VERSION_ID, PHP_WINDOWS_VERSION_BUILD, PhpMixed, defined, disk_free_space, extension_loaded, file_exists, filter_var_boolean, function_exists, get_class_err, hash, implode, ini_get, ioncube_loader_iversion, ioncube_loader_version, is_array, is_string, ob_get_clean, ob_start, phpinfo, rtrim, str_contains, str_replace, @@ -1039,62 +1038,9 @@ impl DiagnoseCommand { return "disabled via disable_functions, using php streams fallback, which reduces performance".to_string(); } - let version = curl_version(); - let version_arr = version.unwrap_or_default(); - let libz_version = version_arr - .get("libz_version") - .and_then(|v| v.as_string()) - .filter(|s| !s.is_empty()) - .unwrap_or("missing") - .to_string(); - let brotli_version = version_arr - .get("brotli_version") - .and_then(|v| v.as_string()) - .filter(|s| !s.is_empty()) - .unwrap_or("missing") - .to_string(); - let ssl_version = version_arr - .get("ssl_version") - .and_then(|v| v.as_string()) - .filter(|s| !s.is_empty()) - .unwrap_or("missing") - .to_string(); - let features = version_arr - .get("features") - .and_then(|v| v.as_int()) - .unwrap_or(0); - let has_zstd = features != 0 - && defined("CURL_VERSION_ZSTD") - && 0 != (features & CURL_VERSION_ZSTD); - let mut http_versions = "1.0, 1.1".to_string(); - if features != 0 - && defined("CURL_VERSION_HTTP2") - && defined("CURL_HTTP_VERSION_2_0") - && (CURL_VERSION_HTTP2 & features) != 0 - { - http_versions.push_str(", 2"); - } - if features != 0 - && defined("CURL_VERSION_HTTP3") - && (features & CURL_VERSION_HTTP3) != 0 - { - http_versions.push_str(", 3"); - } - - let curl_version_str = version_arr - .get("version") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(); - return format!( - "{} libz {} brotli {} zstd {} ssl {} HTTP {}", - curl_version_str, - libz_version, - brotli_version, - if has_zstd { "supported" } else { "missing" }, - ssl_version, - http_versions - ); + // TODO(phase-d): Shirabe does not use cURL, we will consider what should be shown here + // later. + return "TODO: curl_version()".to_string(); } "missing, using php streams fallback, which reduces performance".to_string() diff --git a/crates/shirabe/src/util/http/request_proxy.rs b/crates/shirabe/src/util/http/request_proxy.rs index 876b8cc..49aa885 100644 --- a/crates/shirabe/src/util/http/request_proxy.rs +++ b/crates/shirabe/src/util/http/request_proxy.rs @@ -2,9 +2,8 @@ use indexmap::IndexMap; use shirabe_php_shim::{ - CURL_VERSION_HTTPS_PROXY, CURLAUTH_BASIC, CURLOPT_NOPROXY, CURLOPT_PROXY, CURLOPT_PROXY_CAINFO, - CURLOPT_PROXY_CAPATH, CURLOPT_PROXYAUTH, CURLOPT_PROXYUSERPWD, InvalidArgumentException, - PhpMixed, curl_version, + CURLAUTH_BASIC, CURLOPT_NOPROXY, CURLOPT_PROXY, CURLOPT_PROXY_CAINFO, CURLOPT_PROXY_CAPATH, + CURLOPT_PROXYAUTH, CURLOPT_PROXYUSERPWD, InvalidArgumentException, PhpMixed, }; use crate::downloader::TransportException; @@ -51,13 +50,9 @@ impl RequestProxy { &self, ssl_options: &IndexMap, ) -> Result, TransportException> { - if self.is_secure() && !self.supports_secure_proxy() { - return Err(TransportException::new( - "Cannot use an HTTPS proxy. PHP >= 7.3 and cUrl >= 7.52.0 are required." - .to_string(), - 0, - )); - } + // PHP guards an HTTPS proxy behind `is_secure() && !supports_secure_proxy()` because + // libcurl < 7.52.0 cannot speak TLS to a proxy. Shirabe always can (see + // supports_secure_proxy), so the guard is dropped. let mut options: IndexMap = IndexMap::new(); options.insert( @@ -110,20 +105,10 @@ impl RequestProxy { self.url.as_deref().unwrap_or("").starts_with("https://") } + /// Whether a TLS connection to the proxy itself (an `https://` proxy URL) is supported. + /// In PHP this depends on the libcurl build (`CURL_VERSION_HTTPS_PROXY`, curl >= 7.52.0). + /// Shirabe's HTTP layer is reqwest with a rustls backend, which always supports it. pub fn supports_secure_proxy(&self) -> bool { - let version = match curl_version() { - None => return false, - Some(v) => v, - }; - - if !shirabe_php_shim::defined("CURL_VERSION_HTTPS_PROXY") { - return false; - } - - let features = version - .get("features") - .and_then(|v| v.as_int()) - .unwrap_or(0); - (features & CURL_VERSION_HTTPS_PROXY) != 0 + true } } diff --git a/crates/shirabe/src/util/stream_context_factory.rs b/crates/shirabe/src/util/stream_context_factory.rs index 1747cd6..0b259d7 100644 --- a/crates/shirabe/src/util/stream_context_factory.rs +++ b/crates/shirabe/src/util/stream_context_factory.rs @@ -4,8 +4,8 @@ use indexmap::IndexMap; use shirabe_external_packages::composer::ca_bundle::CaBundle; use shirabe_php_shim::{ HHVM_VERSION, PHP_MAJOR_VERSION, PHP_MINOR_VERSION, PHP_RELEASE_VERSION, PhpMixed, - array_replace_recursive, curl_version, extension_loaded, function_exists, php_uname, - stream_context_create, stripos, uasort, + array_replace_recursive, extension_loaded, function_exists, php_uname, stream_context_create, + stripos, uasort, }; use crate::composer; @@ -159,15 +159,11 @@ impl StreamContextFactory { }; let http_version = if for_curl { - let curl = curl_version().unwrap_or_default(); - let version = curl - .get("version") - .and_then(|v| v.as_string()) - .unwrap_or("") - .to_string(); - format!("cURL {}", version) + // PHP reports `cURL ` here. Shirabe's "curl" transport is backed by reqwest, + // so name reqwest as the HTTP stack in the User-Agent. + "reqwest" } else { - "streams".to_string() + "streams" }; let has_user_agent = options diff --git a/crates/shirabe/tests/command/search_command_test.rs b/crates/shirabe/tests/command/search_command_test.rs index ebdd4bd..69f2930 100644 --- a/crates/shirabe/tests/command/search_command_test.rs +++ b/crates/shirabe/tests/command/search_command_test.rs @@ -36,7 +36,7 @@ fn run_search_case(command: Vec<(PhpMixed, PhpMixed)>, expected: &str) { #[test] #[serial] -#[ignore = "searching a `package`-type repo constructs an HTTP downloader whose User-Agent build calls curl_version() (todo!() in shirabe-php-shim::curl); the HTTP layer is not yet ported"] +#[ignore = "searching a `package`-type repo returns incomplete results (some matching packages are dropped); the search/repository path is not yet fully ported"] fn test_search() { // 'by name and description' run_search_case( -- cgit v1.3.1