Skip to content

Commit 20dd247

Browse files
committed
feat!(client): expose whether a connection is reused from the pool
This introduces a new type `ErrorConnectInfo` that contains information about connection pool as well as transport-related data. This new type can now be obtained from the `Error::connect_info()` method, which means that this is a breaking change as the return type from the method has changed. That said, all information that was available on the previous return type is available on the new type through various getter methods.
1 parent df55aba commit 20dd247

File tree

2 files changed

+45
-10
lines changed

2 files changed

+45
-10
lines changed

src/client/legacy/client.rs

+42-10
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pub struct Error {
5757
kind: ErrorKind,
5858
source: Option<Box<dyn StdError + Send + Sync>>,
5959
#[cfg(any(feature = "http1", feature = "http2"))]
60-
connect_info: Option<Connected>,
60+
connect_info: Option<ErroredConnectInfo>,
6161
}
6262

6363
#[derive(Debug)]
@@ -71,6 +71,34 @@ enum ErrorKind {
7171
SendRequest,
7272
}
7373

74+
/// Extra information about a failed connection.
75+
pub struct ErroredConnectInfo {
76+
conn_info: Connected,
77+
is_reused: bool,
78+
}
79+
80+
impl ErroredConnectInfo {
81+
/// Determines if the connected transport is to an HTTP proxy.
82+
pub fn is_proxied(&self) -> bool {
83+
self.conn_info.is_proxied()
84+
}
85+
86+
/// Copies the extra connection information into an `Extensions` map.
87+
pub fn get_extras(&self, extensions: &mut http::Extensions) {
88+
self.conn_info.get_extras(extensions);
89+
}
90+
91+
/// Determines if the connected transport negotiated HTTP/2 as its next protocol.
92+
pub fn is_negotiated_h2(&self) -> bool {
93+
self.conn_info.is_negotiated_h2()
94+
}
95+
96+
/// Determines if the connection is a reused one from the connection pool.
97+
pub fn is_reused(&self) -> bool {
98+
self.is_reused
99+
}
100+
}
101+
74102
macro_rules! e {
75103
($kind:ident) => {
76104
Error {
@@ -282,7 +310,7 @@ where
282310
if req.version() == Version::HTTP_2 {
283311
warn!("Connection is HTTP/1, but request requires HTTP/2");
284312
return Err(TrySendError::Nope(
285-
e!(UserUnsupportedVersion).with_connect_info(pooled.conn_info.clone()),
313+
e!(UserUnsupportedVersion).with_connect_info(&pooled),
286314
));
287315
}
288316

@@ -317,14 +345,12 @@ where
317345
Err(mut err) => {
318346
return if let Some(req) = err.take_message() {
319347
Err(TrySendError::Retryable {
320-
error: e!(Canceled, err.into_error())
321-
.with_connect_info(pooled.conn_info.clone()),
348+
error: e!(Canceled, err.into_error()).with_connect_info(&pooled),
322349
req,
323350
})
324351
} else {
325352
Err(TrySendError::Nope(
326-
e!(SendRequest, err.into_error())
327-
.with_connect_info(pooled.conn_info.clone()),
353+
e!(SendRequest, err.into_error()).with_connect_info(&pooled),
328354
))
329355
}
330356
}
@@ -464,7 +490,7 @@ where
464490
Ok(checked_out)
465491
}
466492
// Connect won, checkout can just be dropped.
467-
Either::Right((Ok(connected), _checkout)) => Ok(connected),
493+
Either::Right((Ok(connected), _checkout)) => Ok(connected)
468494
// Either checkout or connect could get canceled:
469495
//
470496
// 1. Connect is canceled if this is HTTP/2 and there is
@@ -1619,14 +1645,20 @@ impl Error {
16191645

16201646
/// Returns the info of the client connection on which this error occurred.
16211647
#[cfg(any(feature = "http1", feature = "http2"))]
1622-
pub fn connect_info(&self) -> Option<&Connected> {
1648+
pub fn connect_info(&self) -> Option<&ErroredConnectInfo> {
16231649
self.connect_info.as_ref()
16241650
}
16251651

16261652
#[cfg(any(feature = "http1", feature = "http2"))]
1627-
fn with_connect_info(self, connect_info: Connected) -> Self {
1653+
fn with_connect_info<B>(self, pooled: &pool::Pooled<PoolClient<B>, PoolKey>) -> Self
1654+
where
1655+
B: Send + 'static,
1656+
{
16281657
Self {
1629-
connect_info: Some(connect_info),
1658+
connect_info: Some(ErroredConnectInfo {
1659+
conn_info: pooled.conn_info.clone(),
1660+
is_reused: pooled.is_reused(),
1661+
}),
16301662
..self
16311663
}
16321664
}

src/client/legacy/connect/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ pub trait Connection {
9999
pub struct Connected {
100100
pub(super) alpn: Alpn,
101101
pub(super) is_proxied: bool,
102+
pub(super) is_reused: bool,
102103
pub(super) extra: Option<Extra>,
103104
pub(super) poisoned: PoisonPill,
104105
}
@@ -149,6 +150,7 @@ impl Connected {
149150
Connected {
150151
alpn: Alpn::None,
151152
is_proxied: false,
153+
is_reused: false,
152154
extra: None,
153155
poisoned: PoisonPill::healthy(),
154156
}
@@ -226,6 +228,7 @@ impl Connected {
226228
Connected {
227229
alpn: self.alpn,
228230
is_proxied: self.is_proxied,
231+
is_reused: self.is_reused,
229232
extra: self.extra.clone(),
230233
poisoned: self.poisoned.clone(),
231234
}

0 commit comments

Comments
 (0)