Skip to content

Commit b53e8e7

Browse files
committed
fix: disable multiplexing 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, Cargo can still link against old system libcurl if it is from a custom built one or on macOS. For those cases, multiplexing needs to be disabled when those versions are detected.
1 parent 8e292f6 commit b53e8e7

File tree

1 file changed

+78
-2
lines changed

1 file changed

+78
-2
lines changed

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

+78-2
Original file line numberDiff line numberDiff line change
@@ -1717,8 +1717,12 @@ 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+
let mut http = self.get::<CargoHttpConfig>("http")?;
1722+
let curl_v = curl::Version::get();
1723+
disables_multiplexing_for_bad_curl(curl_v.version(), &mut http, self);
1724+
Ok(http)
1725+
})
17221726
}
17231727

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

0 commit comments

Comments
 (0)