From 947b3c2edab57748cefa77dc546aa977921c0675 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Wed, 14 Oct 2026 12:49:23 -0600 Subject: [PATCH] fix: only instantiate the reqwest client on paths that actually need it --- src/main.rs | 3 +- ...nwritable_log_dir_cli_integration_tests.rs | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index a3fcb839..0dd6140a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -153,7 +153,6 @@ async fn main() -> Result<()> { config.validate(&config_path); config.post_process_initialization(); - let reqwest_client = build_network_client(&config); let (sync_network_tx, sync_network_rx) = mpsc::channel(500); let cancellation_token = CancellationToken::new(); let ctrlc_cancellation_token = cancellation_token.clone(); @@ -185,6 +184,7 @@ async fn main() -> Result<()> { match args.command { Some(command) => match command { Command::Radarr(_) | Command::Sonarr(_) | Command::Lidarr(_) | Command::Readarr(_) => { + let reqwest_client = build_network_client(&config); if spinner_disabled { start_cli_no_spinner( config, @@ -219,6 +219,7 @@ async fn main() -> Result<()> { } }, None => { + let reqwest_client = build_network_client(&config); let app_nw = Arc::clone(&app); std::thread::spawn(move || { start_networking(sync_network_rx, &app_nw, cancellation_token, reqwest_client) diff --git a/tests/unwritable_log_dir_cli_integration_tests.rs b/tests/unwritable_log_dir_cli_integration_tests.rs index 17ffcad4..5c9b4ce8 100644 --- a/tests/unwritable_log_dir_cli_integration_tests.rs +++ b/tests/unwritable_log_dir_cli_integration_tests.rs @@ -43,6 +43,8 @@ impl ProbeEnv { .env("HOME", self.base.join("home")) .env("XDG_CACHE_HOME", self.blocked_cache_dir()) .env("TMPDIR", self.base.join("fresh_tmp")) + .env("SSL_CERT_FILE", self.base.join("no_certs.crt")) + .env("SSL_CERT_DIR", self.base.join("no_certs_dir")) .arg("--config-file") .arg(self.base.join("config.yml")); command @@ -164,6 +166,8 @@ fn unset_home_does_not_panic_on_startup() { .env_clear() .env("PATH", std::env::var_os("PATH").unwrap()) .env("TMPDIR", env.base.join("fresh_tmp")) + .env("SSL_CERT_FILE", env.base.join("no_certs.crt")) + .env("SSL_CERT_DIR", env.base.join("no_certs_dir")) .current_dir(&env.base) .arg("--config-file") .arg(env.base.join("config.yml")) @@ -182,3 +186,49 @@ fn unset_home_does_not_panic_on_startup() { "binary panicked instead of degrading gracefully: {stderr}" ); } + +#[cfg(target_os = "linux")] +#[test] +fn config_path_succeeds_without_loadable_tls_certificates() { + let env = ProbeEnv::new("config_path"); + + let mut command = env.command(); + let assertion = command.arg("config-path").assert().success(); + let output = assertion.get_output(); + let stderr = str::from_utf8(&output.stderr).unwrap(); + + assert!( + !output.stdout.is_empty(), + "config-path produced no stdout despite exiting successfully" + ); + assert!( + !stderr.contains("builder error"), + "config-path built the reqwest client despite needing no network: {stderr}" + ); + assert!( + !stderr.contains("panicked"), + "binary panicked instead of degrading gracefully: {stderr}" + ); +} + +#[cfg(target_os = "linux")] +#[test] +fn servarr_command_without_loadable_tls_certificates_reports_builder_error() { + let env = ProbeEnv::new("servarr_builder_error"); + + let mut command = env.command(); + let assertion = command + .args(["--disable-spinner", "radarr", "list", "movies"]) + .assert() + .failure(); + let stderr = str::from_utf8(&assertion.get_output().stderr).unwrap(); + + assert!( + stderr.contains("error: builder error"), + "network-bound command did not surface the client builder failure: {stderr}" + ); + assert!( + !stderr.contains("panicked"), + "builder failure panicked instead of exiting cleanly: {stderr}" + ); +}