Skip to content

Commit 644083d

Browse files
committed
fix: disable multiplexing on macOS for bad curl
In certain versions of libcurl when proxy is in use with HTTP/2 multiplexing, connections will continue stacking up. This was fixed in libcurl 8.0.0 in curl/curl@821f6e2 However, a custom built Cargo can still link against old system libcurl. Multiplexing needs to be disabled when those versions are detected. We only take care of macOS now, since it is one of the major platforms. For other OS we encourage not to stick to older versions of libcurl.
1 parent 8e292f6 commit 644083d

File tree

1 file changed

+86
-2
lines changed

1 file changed

+86
-2
lines changed

Diff for: src/cargo/util/config/mod.rs

+86-2
Original file line numberDiff line numberDiff line change
@@ -1717,8 +1717,19 @@ impl Config {
17171717
}
17181718

17191719
pub fn http_config(&self) -> CargoResult<&CargoHttpConfig> {
1720-
self.http_config
1721-
.try_borrow_with(|| self.get::<CargoHttpConfig>("http"))
1720+
self.http_config.try_borrow_with(|| {
1721+
#[allow(unused_mut)]
1722+
let mut http = self.get::<CargoHttpConfig>("http")?;
1723+
#[cfg(target_os = "macos")]
1724+
{
1725+
// We only take care of macOS now, since it is one of the major
1726+
// platforms. For other OS we encourage not to stick to older
1727+
// versions of libcurl.
1728+
let curl_v = curl::Version::get();
1729+
disables_multiplexing_for_bad_curl(curl_v.version(), &mut http, self);
1730+
}
1731+
Ok(http)
1732+
})
17221733
}
17231734

17241735
pub fn future_incompat_config(&self) -> CargoResult<&CargoFutureIncompatConfig> {
@@ -2750,3 +2761,76 @@ impl Tool {
27502761
}
27512762
}
27522763
}
2764+
2765+
/// Disable HTTP/2 multiplexing for some broken versions of libcurl.
2766+
///
2767+
/// In certain versions of libcurl when proxy is in use with HTTP/2
2768+
/// multiplexing, connections will continue stacking up. This was
2769+
/// fixed in libcurl 8.0.0 in curl/curl@821f6e2a89de8aec1c7da3c0f381b92b2b801efc
2770+
///
2771+
/// However, a custom built Cargo can still link against old system libcurl.
2772+
/// Multiplexing needs to be disabled when those versions are detected.
2773+
#[allow(dead_code)]
2774+
fn disables_multiplexing_for_bad_curl(
2775+
curl_version: &str,
2776+
http: &mut CargoHttpConfig,
2777+
config: &Config,
2778+
) {
2779+
use crate::util::network;
2780+
2781+
if network::proxy::http_proxy_exists(http, config) && http.multiplexing.is_none() {
2782+
let bad_curl_versions = ["7.87.0", "7.88.0", "7.88.1"];
2783+
if bad_curl_versions
2784+
.iter()
2785+
.any(|v| curl_version.starts_with(v))
2786+
{
2787+
http.multiplexing = Some(false);
2788+
}
2789+
}
2790+
}
2791+
2792+
#[cfg(test)]
2793+
mod tests {
2794+
#[cfg(target_os = "macos")]
2795+
#[test]
2796+
fn disables_multiplexing() {
2797+
use super::disables_multiplexing_for_bad_curl;
2798+
use super::CargoHttpConfig;
2799+
use super::Config;
2800+
use super::Shell;
2801+
2802+
let mut config = Config::new(Shell::new(), "".into(), "".into());
2803+
config.set_search_stop_path(std::path::PathBuf::new());
2804+
config.set_env(Default::default());
2805+
2806+
let mut http = CargoHttpConfig::default();
2807+
http.proxy = Some("127.0.0.1:3128".into());
2808+
disables_multiplexing_for_bad_curl("7.88.1", &mut http, &config);
2809+
assert_eq!(http.multiplexing, Some(false));
2810+
2811+
let cases = [
2812+
(None, None, "7.87.0", None),
2813+
(None, None, "7.88.0", None),
2814+
(None, None, "7.88.1", None),
2815+
(None, None, "8.0.0", None),
2816+
(Some("".into()), None, "7.87.0", Some(false)),
2817+
(Some("".into()), None, "7.88.0", Some(false)),
2818+
(Some("".into()), None, "7.88.1", Some(false)),
2819+
(Some("".into()), None, "8.0.0", None),
2820+
(Some("".into()), Some(false), "7.87.0", Some(false)),
2821+
(Some("".into()), Some(false), "7.88.0", Some(false)),
2822+
(Some("".into()), Some(false), "7.88.1", Some(false)),
2823+
(Some("".into()), Some(false), "8.0.0", Some(false)),
2824+
];
2825+
2826+
for (proxy, multiplexing, curl_v, result) in cases {
2827+
let mut http = CargoHttpConfig {
2828+
multiplexing,
2829+
proxy,
2830+
..Default::default()
2831+
};
2832+
disables_multiplexing_for_bad_curl(curl_v, &mut http, &config);
2833+
assert_eq!(http.multiplexing, result);
2834+
}
2835+
}
2836+
}

0 commit comments

Comments
 (0)