@@ -281,6 +281,55 @@ impl ClientBuilder {
281
281
}
282
282
let http = HttpConnector :: new_with_resolver ( DynResolver :: new ( resolver. clone ( ) ) ) ;
283
283
284
+ #[ cfg( all( feature = "http3" , feature = "__rustls" ) ) ]
285
+ let build_h3_connector =
286
+ |resolver,
287
+ tls,
288
+ quic_max_idle_timeout : Option < Duration > ,
289
+ quic_stream_receive_window,
290
+ quic_receive_window,
291
+ quic_send_window,
292
+ local_address,
293
+ http_version_pref : & HttpVersionPref | {
294
+ let mut transport_config = TransportConfig :: default ( ) ;
295
+
296
+ if let Some ( max_idle_timeout) = quic_max_idle_timeout {
297
+ transport_config. max_idle_timeout ( Some (
298
+ max_idle_timeout. try_into ( ) . map_err ( error:: builder) ?,
299
+ ) ) ;
300
+ }
301
+
302
+ if let Some ( stream_receive_window) = quic_stream_receive_window {
303
+ transport_config. stream_receive_window ( stream_receive_window) ;
304
+ }
305
+
306
+ if let Some ( receive_window) = quic_receive_window {
307
+ transport_config. receive_window ( receive_window) ;
308
+ }
309
+
310
+ if let Some ( send_window) = quic_send_window {
311
+ transport_config. send_window ( send_window) ;
312
+ }
313
+
314
+ let res = H3Connector :: new (
315
+ DynResolver :: new ( resolver) ,
316
+ tls,
317
+ local_address,
318
+ transport_config,
319
+ ) ;
320
+
321
+ match res {
322
+ Ok ( connector) => Ok ( Some ( connector) ) ,
323
+ Err ( err) => {
324
+ if let HttpVersionPref :: Http3 = http_version_pref {
325
+ Err ( error:: builder ( err) )
326
+ } else {
327
+ Ok ( None )
328
+ }
329
+ }
330
+ }
331
+ } ;
332
+
284
333
#[ cfg( feature = "__tls" ) ]
285
334
match config. tls {
286
335
#[ cfg( feature = "default-tls" ) ]
@@ -367,32 +416,16 @@ impl ClientBuilder {
367
416
TlsBackend :: BuiltRustls ( conn) => {
368
417
#[ cfg( feature = "http3" ) ]
369
418
{
370
- let mut transport_config = TransportConfig :: default ( ) ;
371
-
372
- if let Some ( max_idle_timeout) = config. quic_max_idle_timeout {
373
- transport_config. max_idle_timeout ( Some (
374
- max_idle_timeout. try_into ( ) . map_err ( error:: builder) ?,
375
- ) ) ;
376
- }
377
-
378
- if let Some ( stream_receive_window) = config. quic_stream_receive_window {
379
- transport_config. stream_receive_window ( stream_receive_window) ;
380
- }
381
-
382
- if let Some ( receive_window) = config. quic_receive_window {
383
- transport_config. receive_window ( receive_window) ;
384
- }
385
-
386
- if let Some ( send_window) = config. quic_send_window {
387
- transport_config. send_window ( send_window) ;
388
- }
389
-
390
- h3_connector = Some ( H3Connector :: new (
391
- DynResolver :: new ( resolver) ,
419
+ h3_connector = build_h3_connector (
420
+ resolver,
392
421
conn. clone ( ) ,
422
+ config. quic_max_idle_timeout ,
423
+ config. quic_stream_receive_window ,
424
+ config. quic_receive_window ,
425
+ config. quic_send_window ,
393
426
config. local_address ,
394
- transport_config ,
395
- ) ) ;
427
+ & config . http_version_pref ,
428
+ ) ? ;
396
429
}
397
430
398
431
Connector :: new_rustls_tls (
@@ -527,32 +560,16 @@ impl ClientBuilder {
527
560
{
528
561
tls. enable_early_data = config. tls_enable_early_data ;
529
562
530
- let mut transport_config = TransportConfig :: default ( ) ;
531
-
532
- if let Some ( max_idle_timeout) = config. quic_max_idle_timeout {
533
- transport_config. max_idle_timeout ( Some (
534
- max_idle_timeout. try_into ( ) . map_err ( error:: builder) ?,
535
- ) ) ;
536
- }
537
-
538
- if let Some ( stream_receive_window) = config. quic_stream_receive_window {
539
- transport_config. stream_receive_window ( stream_receive_window) ;
540
- }
541
-
542
- if let Some ( receive_window) = config. quic_receive_window {
543
- transport_config. receive_window ( receive_window) ;
544
- }
545
-
546
- if let Some ( send_window) = config. quic_send_window {
547
- transport_config. send_window ( send_window) ;
548
- }
549
-
550
- h3_connector = Some ( H3Connector :: new (
551
- DynResolver :: new ( resolver) ,
563
+ h3_connector = build_h3_connector (
564
+ resolver,
552
565
tls. clone ( ) ,
566
+ config. quic_max_idle_timeout ,
567
+ config. quic_stream_receive_window ,
568
+ config. quic_receive_window ,
569
+ config. quic_send_window ,
553
570
config. local_address ,
554
- transport_config ,
555
- ) ) ;
571
+ & config . http_version_pref ,
572
+ ) ? ;
556
573
}
557
574
558
575
Connector :: new_rustls_tls (
@@ -639,11 +656,15 @@ impl ClientBuilder {
639
656
accepts : config. accepts ,
640
657
#[ cfg( feature = "cookies" ) ]
641
658
cookie_store : config. cookie_store ,
659
+ // Use match instead of map since config is partially moved
660
+ // and it cannot be used in closure
642
661
#[ cfg( feature = "http3" ) ]
643
- h3_client : H3Client :: new (
644
- h3_connector. expect ( "missing HTTP/3 connector" ) ,
645
- config. pool_idle_timeout ,
646
- ) ,
662
+ h3_client : match h3_connector {
663
+ Some ( h3_connector) => {
664
+ Some ( H3Client :: new ( h3_connector, config. pool_idle_timeout ) )
665
+ }
666
+ None => None ,
667
+ } ,
647
668
hyper : builder. build ( connector) ,
648
669
headers : config. headers ,
649
670
redirect_policy : config. redirect_policy ,
@@ -1759,10 +1780,10 @@ impl Client {
1759
1780
1760
1781
let in_flight = match version {
1761
1782
#[ cfg( feature = "http3" ) ]
1762
- http:: Version :: HTTP_3 => {
1783
+ http:: Version :: HTTP_3 if self . inner . h3_client . is_some ( ) => {
1763
1784
let mut req = builder. body ( body) . expect ( "valid request parts" ) ;
1764
1785
* req. headers_mut ( ) = headers. clone ( ) ;
1765
- ResponseFuture :: H3 ( self . inner . h3_client . request ( req) )
1786
+ ResponseFuture :: H3 ( self . inner . h3_client . as_ref ( ) . unwrap ( ) . request ( req) )
1766
1787
}
1767
1788
_ => {
1768
1789
let mut req = builder
@@ -1986,7 +2007,7 @@ struct ClientRef {
1986
2007
headers : HeaderMap ,
1987
2008
hyper : HyperClient ,
1988
2009
#[ cfg( feature = "http3" ) ]
1989
- h3_client : H3Client ,
2010
+ h3_client : Option < H3Client > ,
1990
2011
redirect_policy : redirect:: Policy ,
1991
2012
referer : bool ,
1992
2013
request_timeout : Option < Duration > ,
@@ -2117,7 +2138,13 @@ impl PendingRequest {
2117
2138
. body ( body)
2118
2139
. expect ( "valid request parts" ) ;
2119
2140
* req. headers_mut ( ) = self . headers . clone ( ) ;
2120
- ResponseFuture :: H3 ( self . client . h3_client . request ( req) )
2141
+ ResponseFuture :: H3 (
2142
+ self . client
2143
+ . h3_client
2144
+ . as_ref ( )
2145
+ . expect ( "H3 client must exists, otherwise we can't have a h3 request here" )
2146
+ . request ( req) ,
2147
+ )
2121
2148
}
2122
2149
_ => {
2123
2150
let mut req = hyper:: Request :: builder ( )
@@ -2339,7 +2366,10 @@ impl Future for PendingRequest {
2339
2366
. expect ( "valid request parts" ) ;
2340
2367
* req. headers_mut ( ) = headers. clone ( ) ;
2341
2368
std:: mem:: swap ( self . as_mut ( ) . headers ( ) , & mut headers) ;
2342
- ResponseFuture :: H3 ( self . client . h3_client . request ( req) )
2369
+ ResponseFuture :: H3 ( self . client . h3_client
2370
+ . as_ref ( )
2371
+ . expect ( "H3 client must exists, otherwise we can't have a h3 request here" )
2372
+ . request ( req) )
2343
2373
}
2344
2374
_ => {
2345
2375
let mut req = hyper:: Request :: builder ( )
0 commit comments