@@ -1717,8 +1717,19 @@ impl Config {
1717
1717
}
1718
1718
1719
1719
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
+ } )
1722
1733
}
1723
1734
1724
1735
pub fn future_incompat_config ( & self ) -> CargoResult < & CargoFutureIncompatConfig > {
@@ -2750,3 +2761,76 @@ impl Tool {
2750
2761
}
2751
2762
}
2752
2763
}
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