@@ -1717,8 +1717,12 @@ 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
+ 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
+ } )
1722
1726
}
1723
1727
1724
1728
pub fn future_incompat_config ( & self ) -> CargoResult < & CargoFutureIncompatConfig > {
@@ -2750,3 +2754,75 @@ impl Tool {
2750
2754
}
2751
2755
}
2752
2756
}
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