feat(transport): add connect timeout to Endpoint (#662)
Pulls in [hyper-timeout] which has a connector that can have a timeout applied. I did consider vendoring hyper-timeout since its a fairly small crate. I guess we can always do that later since its not exposed publicly. I would also like to add a test but I'm not sure about the best way of testing this. Fixes https://github.com/hyperium/tonic/issues/498 [hyper-timeout]: https://github.com/hjr3/hyper-timeout Co-authored-by: Lucio Franco <[email protected]>
This commit is contained in:
co-authored by
Lucio Franco
parent
b90bb7bbc0
commit
2b60a00614
@@ -33,6 +33,7 @@ transport = [
|
|||||||
"tracing-futures",
|
"tracing-futures",
|
||||||
"tokio/macros",
|
"tokio/macros",
|
||||||
"tokio/time",
|
"tokio/time",
|
||||||
|
"hyper-timeout",
|
||||||
]
|
]
|
||||||
tls = ["transport", "tokio-rustls"]
|
tls = ["transport", "tokio-rustls"]
|
||||||
tls-roots-common = ["tls"]
|
tls-roots-common = ["tls"]
|
||||||
@@ -74,6 +75,7 @@ tokio = { version = "1.0.1", features = ["net"], optional = true }
|
|||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
tower = { version = "0.4.7", features = ["balance", "buffer", "discover", "limit", "load", "make", "timeout", "util"], optional = true }
|
tower = { version = "0.4.7", features = ["balance", "buffer", "discover", "limit", "load", "make", "timeout", "util"], optional = true }
|
||||||
tracing-futures = { version = "0.2", optional = true }
|
tracing-futures = { version = "0.2", optional = true }
|
||||||
|
hyper-timeout = { version = "0.4", optional = true }
|
||||||
|
|
||||||
# rustls
|
# rustls
|
||||||
tokio-rustls = { version = "0.22", optional = true }
|
tokio-rustls = { version = "0.22", optional = true }
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ pub struct Endpoint {
|
|||||||
pub(crate) http2_keep_alive_interval: Option<Duration>,
|
pub(crate) http2_keep_alive_interval: Option<Duration>,
|
||||||
pub(crate) http2_keep_alive_timeout: Option<Duration>,
|
pub(crate) http2_keep_alive_timeout: Option<Duration>,
|
||||||
pub(crate) http2_keep_alive_while_idle: Option<bool>,
|
pub(crate) http2_keep_alive_while_idle: Option<bool>,
|
||||||
|
pub(crate) connect_timeout: Option<Duration>,
|
||||||
pub(crate) http2_adaptive_window: Option<bool>,
|
pub(crate) http2_adaptive_window: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +120,23 @@ impl Endpoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply a timeout to connecting to the uri.
|
||||||
|
///
|
||||||
|
/// Defaults to no timeout.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use tonic::transport::Endpoint;
|
||||||
|
/// # use std::time::Duration;
|
||||||
|
/// # let mut builder = Endpoint::from_static("https://example.com");
|
||||||
|
/// builder.connect_timeout(Duration::from_secs(5));
|
||||||
|
/// ```
|
||||||
|
pub fn connect_timeout(self, dur: Duration) -> Self {
|
||||||
|
Endpoint {
|
||||||
|
connect_timeout: Some(dur),
|
||||||
|
..self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set whether TCP keepalive messages are enabled on accepted connections.
|
/// Set whether TCP keepalive messages are enabled on accepted connections.
|
||||||
///
|
///
|
||||||
/// If `None` is specified, keepalive is disabled, otherwise the duration
|
/// If `None` is specified, keepalive is disabled, otherwise the duration
|
||||||
@@ -253,7 +271,13 @@ impl Endpoint {
|
|||||||
#[cfg(not(feature = "tls"))]
|
#[cfg(not(feature = "tls"))]
|
||||||
let connector = service::connector(http);
|
let connector = service::connector(http);
|
||||||
|
|
||||||
Channel::connect(connector, self.clone()).await
|
if let Some(connect_timeout) = self.connect_timeout {
|
||||||
|
let mut connector = hyper_timeout::TimeoutConnector::new(connector);
|
||||||
|
connector.set_connect_timeout(Some(connect_timeout));
|
||||||
|
Channel::connect(connector, self.clone()).await
|
||||||
|
} else {
|
||||||
|
Channel::connect(connector, self.clone()).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a channel from this config.
|
/// Create a channel from this config.
|
||||||
@@ -272,7 +296,13 @@ impl Endpoint {
|
|||||||
#[cfg(not(feature = "tls"))]
|
#[cfg(not(feature = "tls"))]
|
||||||
let connector = service::connector(http);
|
let connector = service::connector(http);
|
||||||
|
|
||||||
Ok(Channel::new(connector, self.clone()))
|
if let Some(connect_timeout) = self.connect_timeout {
|
||||||
|
let mut connector = hyper_timeout::TimeoutConnector::new(connector);
|
||||||
|
connector.set_connect_timeout(Some(connect_timeout));
|
||||||
|
Ok(Channel::new(connector, self.clone()))
|
||||||
|
} else {
|
||||||
|
Ok(Channel::new(connector, self.clone()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Connect with a custom connector.
|
/// Connect with a custom connector.
|
||||||
@@ -280,6 +310,8 @@ impl Endpoint {
|
|||||||
/// This allows you to build a [Channel](struct.Channel.html) that uses a non-HTTP transport.
|
/// This allows you to build a [Channel](struct.Channel.html) that uses a non-HTTP transport.
|
||||||
/// See the `uds` example for an example on how to use this function to build channel that
|
/// See the `uds` example for an example on how to use this function to build channel that
|
||||||
/// uses a Unix socket transport.
|
/// uses a Unix socket transport.
|
||||||
|
///
|
||||||
|
/// The [`connect_timeout`](Endpoint::connect_timeout) will still be applied.
|
||||||
pub async fn connect_with_connector<C>(&self, connector: C) -> Result<Channel, Error>
|
pub async fn connect_with_connector<C>(&self, connector: C) -> Result<Channel, Error>
|
||||||
where
|
where
|
||||||
C: MakeConnection<Uri> + Send + 'static,
|
C: MakeConnection<Uri> + Send + 'static,
|
||||||
@@ -293,7 +325,13 @@ impl Endpoint {
|
|||||||
#[cfg(not(feature = "tls"))]
|
#[cfg(not(feature = "tls"))]
|
||||||
let connector = service::connector(connector);
|
let connector = service::connector(connector);
|
||||||
|
|
||||||
Channel::connect(connector, self.clone()).await
|
if let Some(connect_timeout) = self.connect_timeout {
|
||||||
|
let mut connector = hyper_timeout::TimeoutConnector::new(connector);
|
||||||
|
connector.set_connect_timeout(Some(connect_timeout));
|
||||||
|
Channel::connect(connector, self.clone()).await
|
||||||
|
} else {
|
||||||
|
Channel::connect(connector, self.clone()).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the endpoint uri.
|
/// Get the endpoint uri.
|
||||||
@@ -328,6 +366,7 @@ impl From<Uri> for Endpoint {
|
|||||||
http2_keep_alive_interval: None,
|
http2_keep_alive_interval: None,
|
||||||
http2_keep_alive_timeout: None,
|
http2_keep_alive_timeout: None,
|
||||||
http2_keep_alive_while_idle: None,
|
http2_keep_alive_while_idle: None,
|
||||||
|
connect_timeout: None,
|
||||||
http2_adaptive_window: None,
|
http2_adaptive_window: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user