diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-04 13:59:49 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-04 13:59:49 +0900 |
| commit | e6e4f6f6319b39ba3020f96d070b637054c04b6a (patch) | |
| tree | 216423fc61716825f1eded1163e17264dbff3ea1 /crates/mozart/src/commands | |
| parent | 30b222e7324e933f1e1bde5c5e34d588e36adbaa (diff) | |
| download | php-mozart-e6e4f6f6319b39ba3020f96d070b637054c04b6a.tar.gz php-mozart-e6e4f6f6319b39ba3020f96d070b637054c04b6a.tar.zst php-mozart-e6e4f6f6319b39ba3020f96d070b637054c04b6a.zip | |
feat(http): honor config.cafile and config.capath
Composer's config.cafile/config.capath were accepted by the config
command but ignored by every HTTP request. Centralize reqwest client
construction in mozart_core::http, pre-load the configured CA bundle
at startup, and route every callsite (registry, vcs drivers, diagnose,
self-update) through the shared builder so user-supplied roots are
actually used during HTTPS verification.
Diffstat (limited to 'crates/mozart/src/commands')
| -rw-r--r-- | crates/mozart/src/commands/config_helpers.rs | 47 | ||||
| -rw-r--r-- | crates/mozart/src/commands/diagnose.rs | 6 | ||||
| -rw-r--r-- | crates/mozart/src/commands/self_update.rs | 6 |
3 files changed, 51 insertions, 8 deletions
diff --git a/crates/mozart/src/commands/config_helpers.rs b/crates/mozart/src/commands/config_helpers.rs index 9b60129..422db4d 100644 --- a/crates/mozart/src/commands/config_helpers.rs +++ b/crates/mozart/src/commands/config_helpers.rs @@ -68,6 +68,53 @@ pub(crate) fn working_dir(cli: &super::Cli) -> anyhow::Result<PathBuf> { } } +/// Read TLS-related options (`config.cafile`, `config.capath`) from the merged +/// global + local config. Local values override global. Relative paths are +/// resolved against the directory of the config file that defined them. +pub(crate) fn load_tls_options(cli: &super::Cli) -> mozart_core::http::TlsOptions { + let mut opts = mozart_core::http::TlsOptions::default(); + + let home = composer_home(); + apply_tls_from_file(&home.join("config.json"), &home, &mut opts); + + if let Ok(wd) = working_dir(cli) { + apply_tls_from_file(&wd.join("composer.json"), &wd, &mut opts); + } + + opts +} + +fn apply_tls_from_file(path: &Path, base_dir: &Path, opts: &mut mozart_core::http::TlsOptions) { + let Ok(content) = std::fs::read_to_string(path) else { + return; + }; + let Ok(json) = serde_json::from_str::<serde_json::Value>(&content) else { + return; + }; + let Some(cfg) = json.get("config").and_then(|v| v.as_object()) else { + return; + }; + if let Some(s) = cfg.get("cafile").and_then(|v| v.as_str()) + && !s.is_empty() + { + opts.cafile = Some(resolve_relative(s, base_dir)); + } + if let Some(s) = cfg.get("capath").and_then(|v| v.as_str()) + && !s.is_empty() + { + opts.capath = Some(resolve_relative(s, base_dir)); + } +} + +fn resolve_relative(path: &str, base: &Path) -> PathBuf { + let p = Path::new(path); + if p.is_absolute() { + p.to_path_buf() + } else { + base.join(p) + } +} + /// Read a JSON file as `serde_json::Value`. /// If the file does not exist, return a default skeleton: /// `{"config": {}}` for global files, `{}` for local. diff --git a/crates/mozart/src/commands/diagnose.rs b/crates/mozart/src/commands/diagnose.rs index bb6e886..2320ddc 100644 --- a/crates/mozart/src/commands/diagnose.rs +++ b/crates/mozart/src/commands/diagnose.rs @@ -92,9 +92,8 @@ async fn check_http_connectivity(url: &str) -> CheckResult { return CheckResult::Skip("COMPOSER_DISABLE_NETWORK is set".to_string()); } - let client = match reqwest::Client::builder() + let client = match mozart_core::http::client_builder() .timeout(std::time::Duration::from_secs(10)) - .user_agent(mozart_core::http::user_agent()) .build() { Ok(c) => c, @@ -120,9 +119,8 @@ async fn check_github_api() -> CheckResult { return CheckResult::Skip("COMPOSER_DISABLE_NETWORK is set".to_string()); } - let client = match reqwest::Client::builder() + let client = match mozart_core::http::client_builder() .timeout(std::time::Duration::from_secs(10)) - .user_agent(mozart_core::http::user_agent()) .build() { Ok(c) => c, diff --git a/crates/mozart/src/commands/self_update.rs b/crates/mozart/src/commands/self_update.rs index afc77f3..2c7c59b 100644 --- a/crates/mozart/src/commands/self_update.rs +++ b/crates/mozart/src/commands/self_update.rs @@ -150,9 +150,8 @@ fn version_from_backup(path: &Path) -> String { async fn fetch_releases(include_prerelease: bool) -> anyhow::Result<Vec<GitHubRelease>> { let url = format!("{GITHUB_API_BASE}/{GITHUB_REPO}/releases"); - let client = reqwest::Client::builder() + let client = mozart_core::http::client_builder() .timeout(std::time::Duration::from_secs(30)) - .user_agent(mozart_core::http::user_agent()) .build() .map_err(|e| anyhow::anyhow!("Could not build HTTP client: {e}"))?; @@ -230,9 +229,8 @@ async fn download_asset( show_progress: bool, console: &mozart_core::console::Console, ) -> anyhow::Result<()> { - let client = reqwest::Client::builder() + let client = mozart_core::http::client_builder() .timeout(std::time::Duration::from_secs(300)) - .user_agent(mozart_core::http::user_agent()) .build() .map_err(|e| anyhow::anyhow!("Could not build HTTP client: {e}"))?; |
