@@ -576,22 +576,89 @@ where
576
576
panic ! ( "http2 feature is not enabled" ) ;
577
577
} else {
578
578
#[ cfg( feature = "http1" ) ] {
579
+ // Perform the HTTP/1.1 handshake on the provided I/O stream.
580
+ // Uses the h1_builder to establish a connection, returning a sender (tx) for requests
581
+ // and a connection task (conn) that manages the connection lifecycle.
579
582
let ( mut tx, conn) =
580
- h1_builder. handshake ( io) . await . map_err ( Error :: tx) ?;
583
+ h1_builder. handshake ( io) . await . map_err ( crate :: client :: legacy :: client :: Error :: tx) ?;
581
584
585
+ // Log that the HTTP/1.1 handshake has completed successfully.
586
+ // This indicates the connection is established and ready for request processing.
582
587
trace ! (
583
588
"http1 handshake complete, spawning background dispatcher task"
584
589
) ;
590
+ // Create a oneshot channel to communicate errors from the connection task.
591
+ // err_tx sends errors from the connection task, and err_rx receives them
592
+ // to correlate connection failures with request readiness errors.
593
+ let ( err_tx, err_rx) = tokio:: sync:: oneshot:: channel ( ) ;
594
+ // Spawn the connection task in the background using the executor.
595
+ // The task manages the HTTP/1.1 connection, including upgrades (e.g., WebSocket).
596
+ // Errors are sent via err_tx to ensure they can be checked if the sender (tx) fails.
585
597
executor. execute (
586
598
conn. with_upgrades ( )
587
- . map_err ( |e| debug ! ( "client connection error: {}" , e) )
599
+ . map_err ( |e| {
600
+ // Log the connection error at debug level for diagnostic purposes.
601
+ debug ! ( "client connection error: {:?}" , e) ;
602
+ // Log that the error is being sent to the error channel.
603
+ trace ! ( "sending connection error to error channel" ) ;
604
+ // Send the error via the oneshot channel, ignoring send failures
605
+ // (e.g., if the receiver is dropped, which is handled later).
606
+ let _ =err_tx. send ( e) ;
607
+ } )
588
608
. map ( |_| ( ) ) ,
589
609
) ;
590
-
610
+ // Log that the client is waiting for the connection to be ready.
611
+ // Readiness indicates the sender (tx) can accept a request without blocking.
612
+ trace ! ( "waiting for connection to be ready" ) ;
613
+ // Check if the sender is ready to accept a request.
614
+ // This ensures the connection is fully established before proceeding.
615
+ // aka:
591
616
// Wait for 'conn' to ready up before we
592
617
// declare this tx as usable
593
- tx. ready ( ) . await . map_err ( Error :: tx) ?;
594
- PoolTx :: Http1 ( tx)
618
+ match tx. ready ( ) . await {
619
+ // If ready, the connection is usable for sending requests.
620
+ Ok ( _) => {
621
+ // Log that the connection is ready for use.
622
+ trace ! ( "connection is ready" ) ;
623
+ // Drop the error receiver, as it’s no longer needed since the sender is ready.
624
+ // This prevents waiting for errors that won’t occur in a successful case.
625
+ drop ( err_rx) ;
626
+ // Wrap the sender in PoolTx::Http1 for use in the connection pool.
627
+ PoolTx :: Http1 ( tx)
628
+ }
629
+ // If the sender fails with a closed channel error, check for a specific connection error.
630
+ // This distinguishes between a vague ChannelClosed error and an actual connection failure.
631
+ Err ( e) if e. is_closed ( ) => {
632
+ // Log that the channel is closed, indicating a potential connection issue.
633
+ trace ! ( "connection channel closed, checking for connection error" ) ;
634
+ // Check the oneshot channel for a specific error from the connection task.
635
+ match err_rx. await {
636
+ // If an error was received, it’s a specific connection failure.
637
+ Ok ( err) => {
638
+ // Log the specific connection error for diagnostics.
639
+ trace ! ( "received connection error: {:?}" , err) ;
640
+ // Return the error wrapped in Error::tx to propagate it.
641
+ return Err ( crate :: client:: legacy:: client:: Error :: tx ( err) ) ;
642
+ }
643
+ // If the error channel is closed, no specific error was sent.
644
+ // Fall back to the vague ChannelClosed error.
645
+ Err ( _) => {
646
+ // Log that the error channel is closed, indicating no specific error.
647
+ trace ! ( "error channel closed, returning the vague ChannelClosed error" ) ;
648
+ // Return the original error wrapped in Error::tx.
649
+ return Err ( crate :: client:: legacy:: client:: Error :: tx ( e) ) ;
650
+ }
651
+ }
652
+ }
653
+ // For other errors (e.g., timeout, I/O issues), propagate them directly.
654
+ // These are not ChannelClosed errors and don’t require error channel checks.
655
+ Err ( e) => {
656
+ // Log the specific readiness failure for diagnostics.
657
+ trace ! ( "connection readiness failed: {:?}" , e) ;
658
+ // Return the error wrapped in Error::tx to propagate it.
659
+ return Err ( crate :: client:: legacy:: client:: Error :: tx ( e) ) ;
660
+ }
661
+ }
595
662
}
596
663
#[ cfg( not( feature = "http1" ) ) ] {
597
664
panic ! ( "http1 feature is not enabled" ) ;
0 commit comments