diff --git a/src/client/legacy/client.rs b/src/client/legacy/client.rs index 8562584..501f28b 100644 --- a/src/client/legacy/client.rs +++ b/src/client/legacy/client.rs @@ -57,7 +57,7 @@ pub struct Error { kind: ErrorKind, source: Option>, #[cfg(any(feature = "http1", feature = "http2"))] - connect_info: Option, + connect_info: Option, } #[derive(Debug)] @@ -71,6 +71,34 @@ enum ErrorKind { SendRequest, } +/// Extra information about a failed connection. +pub struct ErroredConnectInfo { + conn_info: Connected, + is_reused: bool, +} + +impl ErroredConnectInfo { + /// Determines if the connected transport is to an HTTP proxy. + pub fn is_proxied(&self) -> bool { + self.conn_info.is_proxied() + } + + /// Copies the extra connection information into an `Extensions` map. + pub fn get_extras(&self, extensions: &mut http::Extensions) { + self.conn_info.get_extras(extensions); + } + + /// Determines if the connected transport negotiated HTTP/2 as its next protocol. + pub fn is_negotiated_h2(&self) -> bool { + self.conn_info.is_negotiated_h2() + } + + /// Determines if the connection is a reused one from the connection pool. + pub fn is_reused(&self) -> bool { + self.is_reused + } +} + macro_rules! e { ($kind:ident) => { Error { @@ -282,7 +310,7 @@ where if req.version() == Version::HTTP_2 { warn!("Connection is HTTP/1, but request requires HTTP/2"); return Err(TrySendError::Nope( - e!(UserUnsupportedVersion).with_connect_info(pooled.conn_info.clone()), + e!(UserUnsupportedVersion).with_connect_info(&pooled), )); } @@ -317,14 +345,12 @@ where Err(mut err) => { return if let Some(req) = err.take_message() { Err(TrySendError::Retryable { - error: e!(Canceled, err.into_error()) - .with_connect_info(pooled.conn_info.clone()), + error: e!(Canceled, err.into_error()).with_connect_info(&pooled), req, }) } else { Err(TrySendError::Nope( - e!(SendRequest, err.into_error()) - .with_connect_info(pooled.conn_info.clone()), + e!(SendRequest, err.into_error()).with_connect_info(&pooled), )) } } @@ -464,7 +490,7 @@ where Ok(checked_out) } // Connect won, checkout can just be dropped. - Either::Right((Ok(connected), _checkout)) => Ok(connected), + Either::Right((Ok(connected), _checkout)) => Ok(connected) // Either checkout or connect could get canceled: // // 1. Connect is canceled if this is HTTP/2 and there is @@ -1619,14 +1645,20 @@ impl Error { /// Returns the info of the client connection on which this error occurred. #[cfg(any(feature = "http1", feature = "http2"))] - pub fn connect_info(&self) -> Option<&Connected> { + pub fn connect_info(&self) -> Option<&ErroredConnectInfo> { self.connect_info.as_ref() } #[cfg(any(feature = "http1", feature = "http2"))] - fn with_connect_info(self, connect_info: Connected) -> Self { + fn with_connect_info(self, pooled: &pool::Pooled, PoolKey>) -> Self + where + B: Send + 'static, + { Self { - connect_info: Some(connect_info), + connect_info: Some(ErroredConnectInfo { + conn_info: pooled.conn_info.clone(), + is_reused: pooled.is_reused(), + }), ..self } } diff --git a/src/client/legacy/connect/mod.rs b/src/client/legacy/connect/mod.rs index e3369b5..9435334 100644 --- a/src/client/legacy/connect/mod.rs +++ b/src/client/legacy/connect/mod.rs @@ -99,6 +99,7 @@ pub trait Connection { pub struct Connected { pub(super) alpn: Alpn, pub(super) is_proxied: bool, + pub(super) is_reused: bool, pub(super) extra: Option, pub(super) poisoned: PoisonPill, } @@ -149,6 +150,7 @@ impl Connected { Connected { alpn: Alpn::None, is_proxied: false, + is_reused: false, extra: None, poisoned: PoisonPill::healthy(), } @@ -226,6 +228,7 @@ impl Connected { Connected { alpn: self.alpn, is_proxied: self.is_proxied, + is_reused: self.is_reused, extra: self.extra.clone(), poisoned: self.poisoned.clone(), }