diff --git a/crates/pixi_utils/src/reqwest.rs b/crates/pixi_utils/src/reqwest.rs index 951f019a56..d154deb823 100644 --- a/crates/pixi_utils/src/reqwest.rs +++ b/crates/pixi_utils/src/reqwest.rs @@ -180,12 +180,57 @@ pub fn build_reqwest_clients( } pub fn uv_middlewares(config: &Config) -> Vec> { - if config.mirror_map().is_empty() { + let mut middlewares: Vec> = if config.mirror_map().is_empty() { vec![] } else { vec![ Arc::new(mirror_middleware(config)), Arc::new(oci_middleware()), ] + }; + + // Add authentication middleware after mirror rewriting so it can authenticate + // against the rewritten URLs (important for mirrors that require different credentials) + if let Ok(auth_middleware) = auth_middleware(config) { + middlewares.push(Arc::new(auth_middleware)); + } + middlewares +} + +#[cfg(test)] +mod tests { + use super::*; + use pixi_config::Config; + use url::Url; + + #[test] + fn test_uv_middlewares_includes_auth_with_mirrors() { + // Test that authentication middleware is included when mirrors are configured + // This ensures credentials work with rewritten mirror URLs + let mut config = Config::default(); + config.mirrors.insert( + Url::parse("https://pypi.org/simple/").unwrap(), + vec![Url::parse("https://my-mirror.example.com/simple/").unwrap()], + ); + + let middlewares = uv_middlewares(&config); + + // Should have: mirror + OCI + auth middleware + assert!(middlewares.len() >= 3, + "Expected at least 3 middlewares (mirror, OCI, auth) when mirrors configured, got {}", + middlewares.len()); + } + + #[test] + fn test_uv_middlewares_includes_auth_without_mirrors() { + // Test that authentication middleware is still included even without mirrors + // This ensures existing non-mirror auth scenarios continue to work + let config = Config::default(); + let middlewares = uv_middlewares(&config); + + // Should have: auth middleware only + assert_eq!(middlewares.len(), 1, + "Expected exactly 1 middleware (auth) when no mirrors configured, got {}", + middlewares.len()); } }