@@ -72,6 +72,7 @@ use crate::core::{features, CliUnstable, Shell, SourceId, Workspace, WorkspaceRo
72
72
use crate :: ops:: { self , RegistryCredentialConfig } ;
73
73
use crate :: util:: auth:: Secret ;
74
74
use crate :: util:: errors:: CargoResult ;
75
+ use crate :: util:: network;
75
76
use crate :: util:: CanonicalUrl ;
76
77
use crate :: util:: { internal, toml as cargo_toml} ;
77
78
use crate :: util:: { try_canonicalize, validate_package_name} ;
@@ -1717,18 +1718,16 @@ impl Config {
1717
1718
}
1718
1719
1719
1720
pub fn http_config ( & self ) -> CargoResult < & CargoHttpConfig > {
1720
- self . http_config
1721
- . try_borrow_with ( || {
1722
- let http_config = self . get :: < CargoHttpConfig > ( "http" ) ?;
1723
- if cfg ! ( target_os = "macos" ) {
1724
- let versions = [ "7.87" , "7.88" ] ;
1725
- let curl_v = curl:: Version :: get ( ) . version ( ) ;
1726
- if versions. iter ( ) . any ( |v| curl_v. starts_with ( v) ) {
1727
- http_config. multiplexing = Some ( false ) ;
1728
- }
1729
- }
1730
- Ok ( http_config)
1731
- } )
1721
+ self . http_config . try_borrow_with ( || {
1722
+ let http = self . get :: < CargoHttpConfig > ( "http" ) ?;
1723
+ #[ cfg( target_os = "macos" ) ]
1724
+ {
1725
+ let mut http = http;
1726
+ let curl_v = curl:: Version :: get ( ) ;
1727
+ disables_multiplexing_for_bad_curl ( curl_v. version ( ) , & mut http, self ) ;
1728
+ }
1729
+ Ok ( http)
1730
+ } )
1732
1731
}
1733
1732
1734
1733
pub fn future_incompat_config ( & self ) -> CargoResult < & CargoFutureIncompatConfig > {
@@ -2760,3 +2759,76 @@ impl Tool {
2760
2759
}
2761
2760
}
2762
2761
}
2762
+
2763
+ /// Disable HTTP/2 multiplexing for some broken versions of libcurl.
2764
+ ///
2765
+ /// In certain versions of libcurl when proxy is in use with HTTP/2
2766
+ /// multiplexing, connections will continue stacking up. This was
2767
+ /// fixed in libcurl 8.0.0 in curl/curl@821f6e2a89de8aec1c7da3c0f381b92b2b801efc
2768
+ ///
2769
+ /// However, a custom built Cargo can still link against old system libcurl.
2770
+ /// Multiplexing needs to be disabled when those versions are detected.
2771
+ ///
2772
+ /// We only take care of macOS now, since it is one of the major platforms.
2773
+ /// For other OS we encourage not to stick to older versions of licurl.
2774
+ #[ cfg( target_os = "macos" ) ]
2775
+ fn disables_multiplexing_for_bad_curl (
2776
+ curl_version : & str ,
2777
+ http : & mut CargoHttpConfig ,
2778
+ config : & Config ,
2779
+ ) {
2780
+ if network:: proxy:: http_proxy_exists ( http, config) && http. multiplexing . is_none ( ) {
2781
+ let bad_curl_versions = [ "7.87" , "7.88" ] ;
2782
+ if bad_curl_versions
2783
+ . iter ( )
2784
+ . any ( |v| curl_version. starts_with ( v) )
2785
+ {
2786
+ http. multiplexing = Some ( false ) ;
2787
+ }
2788
+ }
2789
+ }
2790
+
2791
+ #[ cfg( test) ]
2792
+ mod tests {
2793
+ use super :: disables_multiplexing_for_bad_curl;
2794
+ use super :: CargoHttpConfig ;
2795
+ use super :: Config ;
2796
+ use super :: Shell ;
2797
+
2798
+ #[ cfg( target_os = "macos" ) ]
2799
+ #[ test]
2800
+ fn disables_multiplexing ( ) {
2801
+ let mut config = Config :: new ( Shell :: new ( ) , "" . into ( ) , "" . into ( ) ) ;
2802
+ config. set_search_stop_path ( std:: path:: PathBuf :: new ( ) ) ;
2803
+ config. set_env ( Default :: default ( ) ) ;
2804
+
2805
+ let mut http = CargoHttpConfig :: default ( ) ;
2806
+ http. proxy = Some ( "127.0.0.1:3128" . into ( ) ) ;
2807
+ disables_multiplexing_for_bad_curl ( "7.88.1" , & mut http, & config) ;
2808
+ assert_eq ! ( http. multiplexing, Some ( false ) ) ;
2809
+
2810
+ let cases = [
2811
+ ( None , None , "7.87.0" , None ) ,
2812
+ ( None , None , "7.88.0" , None ) ,
2813
+ ( None , None , "7.88.1" , None ) ,
2814
+ ( None , None , "8.0.0" , None ) ,
2815
+ ( Some ( "" . into ( ) ) , None , "7.87.0" , Some ( false ) ) ,
2816
+ ( Some ( "" . into ( ) ) , None , "7.88.0" , Some ( false ) ) ,
2817
+ ( Some ( "" . into ( ) ) , None , "7.88.1" , Some ( false ) ) ,
2818
+ ( Some ( "" . into ( ) ) , None , "8.0.0" , None ) ,
2819
+ ( Some ( "" . into ( ) ) , Some ( false ) , "7.87.0" , Some ( false ) ) ,
2820
+ ( Some ( "" . into ( ) ) , Some ( false ) , "7.88.0" , Some ( false ) ) ,
2821
+ ( Some ( "" . into ( ) ) , Some ( false ) , "7.88.1" , Some ( false ) ) ,
2822
+ ( Some ( "" . into ( ) ) , Some ( false ) , "8.0.0" , Some ( false ) ) ,
2823
+ ] ;
2824
+ for ( proxy, multiplexing, curl_v, result) in cases {
2825
+ let mut http = CargoHttpConfig {
2826
+ multiplexing,
2827
+ proxy,
2828
+ ..Default :: default ( )
2829
+ } ;
2830
+ disables_multiplexing_for_bad_curl ( curl_v, & mut http, & config) ;
2831
+ assert_eq ! ( http. multiplexing, result) ;
2832
+ }
2833
+ }
2834
+ }
0 commit comments