diff --git a/tonic/src/transport/channel/endpoint.rs b/tonic/src/transport/channel/endpoint.rs index aaf977346..b781cd66e 100644 --- a/tonic/src/transport/channel/endpoint.rs +++ b/tonic/src/transport/channel/endpoint.rs @@ -9,9 +9,11 @@ use bytes::Bytes; use http::{uri::Uri, HeaderValue}; use hyper::rt; use hyper_util::client::legacy::connect::HttpConnector; -use std::{fmt, future::Future, pin::Pin, str::FromStr, time::Duration}; +use std::{fmt, future::Future, net::IpAddr, pin::Pin, str::FromStr, time::Duration}; use tower_service::Service; +// use crate::transport::E + /// Channel builder. /// /// This struct is used to build and configure HTTP/2 channels. @@ -37,6 +39,7 @@ pub struct Endpoint { pub(crate) connect_timeout: Option, pub(crate) http2_adaptive_window: Option, pub(crate) executor: SharedExec, + pub(crate) local_address: Option, } impl Endpoint { @@ -324,6 +327,23 @@ impl Endpoint { self.tls.clone(), ) } + + /// Set the local address + /// + /// This sets the IP address the client will use. By default we let hyper select the IP address. + /// ``` + /// # use std::net::IpAddr; + /// # use std::str::FromStr; + /// # use tonic::transport::Endpoint; + /// # let mut builder = Endpoint::from_static("https://example.com"); + /// # builder.local_address(IpAddr::from_str("127.0.0.1").expect("Unable to parse IP address")); + /// ``` + pub fn local_address(self, addr: IpAddr) -> Self { + Endpoint { + local_address: Some(addr), + ..self + } + } /// Create a channel from this config. pub async fn connect(&self) -> Result { @@ -332,6 +352,7 @@ impl Endpoint { http.set_nodelay(self.tcp_nodelay); http.set_keepalive(self.tcp_keepalive); http.set_connect_timeout(self.connect_timeout); + http.set_local_address(self.local_address); let connector = self.connector(http); @@ -440,6 +461,7 @@ impl From for Endpoint { connect_timeout: None, http2_adaptive_window: None, executor: SharedExec::tokio(), + local_address: None, } } }