aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart/src/commands/config_helpers.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-04 13:59:49 +0900
committernsfisis <nsfisis@gmail.com>2026-05-04 13:59:49 +0900
commite6e4f6f6319b39ba3020f96d070b637054c04b6a (patch)
tree216423fc61716825f1eded1163e17264dbff3ea1 /crates/mozart/src/commands/config_helpers.rs
parent30b222e7324e933f1e1bde5c5e34d588e36adbaa (diff)
downloadphp-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/config_helpers.rs')
-rw-r--r--crates/mozart/src/commands/config_helpers.rs47
1 files changed, 47 insertions, 0 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.