Add tcp_nodelay for Builder
This commit is contained in:
		| @@ -81,6 +81,7 @@ struct Config { | |||||||
|     http2_only: bool, |     http2_only: bool, | ||||||
|     http1_title_case_headers: bool, |     http1_title_case_headers: bool, | ||||||
|     local_address: Option<IpAddr>, |     local_address: Option<IpAddr>, | ||||||
|  |     nodelay: bool, | ||||||
| } | } | ||||||
|  |  | ||||||
| impl ClientBuilder { | impl ClientBuilder { | ||||||
| @@ -115,6 +116,7 @@ impl ClientBuilder { | |||||||
|                 http2_only: false, |                 http2_only: false, | ||||||
|                 http1_title_case_headers: false, |                 http1_title_case_headers: false, | ||||||
|                 local_address: None, |                 local_address: None, | ||||||
|  |                 nodelay: false | ||||||
|             }, |             }, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -146,7 +148,7 @@ impl ClientBuilder { | |||||||
|                         id.add_to_native_tls(&mut tls)?; |                         id.add_to_native_tls(&mut tls)?; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     Connector::new_default_tls(tls, proxies.clone(), config.local_address)? |                     Connector::new_default_tls(tls, proxies.clone(), config.local_address, config.nodelay)? | ||||||
|                 }, |                 }, | ||||||
|                 #[cfg(feature = "rustls-tls")] |                 #[cfg(feature = "rustls-tls")] | ||||||
|                 TlsBackend::Rustls => { |                 TlsBackend::Rustls => { | ||||||
| @@ -175,12 +177,12 @@ impl ClientBuilder { | |||||||
|                         id.add_to_rustls(&mut tls)?; |                         id.add_to_rustls(&mut tls)?; | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     Connector::new_rustls_tls(tls, proxies.clone(), config.local_address)? |                     Connector::new_rustls_tls(tls, proxies.clone(), config.local_address, config.nodelay)? | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             #[cfg(not(feature = "tls"))] |             #[cfg(not(feature = "tls"))] | ||||||
|             Connector::new(proxies.clone(), config.local_address)? |             Connector::new(proxies.clone(), config.local_address, config.nodelay)? | ||||||
|         }; |         }; | ||||||
|  |  | ||||||
|         connector.set_timeout(config.connect_timeout); |         connector.set_timeout(config.connect_timeout); | ||||||
| @@ -215,6 +217,12 @@ impl ClientBuilder { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Set that all sockets have `SO_NODELAY` set to `true`. | ||||||
|  |     pub fn tcp_nodelay(mut self) -> ClientBuilder { | ||||||
|  |         self.config.nodelay = true; | ||||||
|  |         self | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Use native TLS backend. |     /// Use native TLS backend. | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "default-tls")] | ||||||
|     pub fn use_default_tls(mut self) -> ClientBuilder { |     pub fn use_default_tls(mut self) -> ClientBuilder { | ||||||
|   | |||||||
| @@ -84,6 +84,11 @@ impl ClientBuilder { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /// Set that all sockets have `SO_NODELAY` set to `true`. | ||||||
|  |     pub fn tcp_nodelay(self) -> ClientBuilder { | ||||||
|  |         self.with_inner(move |inner| inner.tcp_nodelay()) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /// Use native TLS backend. |     /// Use native TLS backend. | ||||||
|     #[cfg(feature = "default-tls")] |     #[cfg(feature = "default-tls")] | ||||||
|     pub fn use_default_tls(self) -> ClientBuilder { |     pub fn use_default_tls(self) -> ClientBuilder { | ||||||
|   | |||||||
| @@ -31,6 +31,8 @@ pub(crate) struct Connector { | |||||||
|     inner: Inner, |     inner: Inner, | ||||||
|     proxies: Arc<Vec<Proxy>>, |     proxies: Arc<Vec<Proxy>>, | ||||||
|     timeout: Option<Duration>, |     timeout: Option<Duration>, | ||||||
|  |     #[cfg(feature = "tls")] | ||||||
|  |     nodelay: bool | ||||||
| } | } | ||||||
|  |  | ||||||
| enum Inner { | enum Inner { | ||||||
| @@ -48,13 +50,14 @@ enum Inner { | |||||||
|  |  | ||||||
| impl Connector { | impl Connector { | ||||||
|     #[cfg(not(feature = "tls"))] |     #[cfg(not(feature = "tls"))] | ||||||
|     pub(crate) fn new<T>(proxies: Arc<Vec<Proxy>>, local_addr: T) -> ::Result<Connector> |     pub(crate) fn new<T>(proxies: Arc<Vec<Proxy>>, local_addr: T, nodelay: bool) -> ::Result<Connector> | ||||||
|     where |     where | ||||||
|         T: Into<Option<IpAddr>> |         T: Into<Option<IpAddr>> | ||||||
|     { |     { | ||||||
|  |  | ||||||
|         let mut http = http_connector()?; |         let mut http = http_connector()?; | ||||||
|         http.set_local_address(local_addr.into()); |         http.set_local_address(local_addr.into()); | ||||||
|  |         http.set_nodelay(nodelay); | ||||||
|         Ok(Connector { |         Ok(Connector { | ||||||
|             inner: Inner::Http(http), |             inner: Inner::Http(http), | ||||||
|             proxies, |             proxies, | ||||||
| @@ -66,7 +69,8 @@ impl Connector { | |||||||
|     pub(crate) fn new_default_tls<T>( |     pub(crate) fn new_default_tls<T>( | ||||||
|         tls: TlsConnectorBuilder, |         tls: TlsConnectorBuilder, | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         local_addr: T) -> ::Result<Connector> |         local_addr: T, | ||||||
|  |         nodelay: bool) -> ::Result<Connector> | ||||||
|         where |         where | ||||||
|             T: Into<Option<IpAddr>>, |             T: Into<Option<IpAddr>>, | ||||||
|     { |     { | ||||||
| @@ -80,6 +84,7 @@ impl Connector { | |||||||
|             inner: Inner::DefaultTls(http, tls), |             inner: Inner::DefaultTls(http, tls), | ||||||
|             proxies, |             proxies, | ||||||
|             timeout: None, |             timeout: None, | ||||||
|  |             nodelay | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -87,7 +92,8 @@ impl Connector { | |||||||
|     pub(crate) fn new_rustls_tls<T>( |     pub(crate) fn new_rustls_tls<T>( | ||||||
|         tls: rustls::ClientConfig, |         tls: rustls::ClientConfig, | ||||||
|         proxies: Arc<Vec<Proxy>>, |         proxies: Arc<Vec<Proxy>>, | ||||||
|         local_addr: T) -> ::Result<Connector> |         local_addr: T, | ||||||
|  |         nodelay: bool) -> ::Result<Connector> | ||||||
|         where |         where | ||||||
|             T: Into<Option<IpAddr>>, |             T: Into<Option<IpAddr>>, | ||||||
|     { |     { | ||||||
| @@ -108,6 +114,7 @@ impl Connector { | |||||||
|             inner: Inner::RustlsTls { http, tls, tls_proxy }, |             inner: Inner::RustlsTls { http, tls, tls_proxy }, | ||||||
|             proxies, |             proxies, | ||||||
|             timeout: None, |             timeout: None, | ||||||
|  |             nodelay | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -134,6 +141,9 @@ impl Connect for Connector { | |||||||
|     type Future = Connecting; |     type Future = Connecting; | ||||||
|  |  | ||||||
|     fn connect(&self, dst: Destination) -> Self::Future { |     fn connect(&self, dst: Destination) -> Self::Future { | ||||||
|  |         #[cfg(feature = "tls")] | ||||||
|  |         let nodelay = self.nodelay; | ||||||
|  |  | ||||||
|         macro_rules! timeout { |         macro_rules! timeout { | ||||||
|             ($future:expr) => { |             ($future:expr) => { | ||||||
|                 if let Some(dur) = self.timeout { |                 if let Some(dur) = self.timeout { | ||||||
| @@ -163,33 +173,27 @@ impl Connect for Connector { | |||||||
|                     Inner::Http(http) => connect!(http, $dst, $proxy), |                     Inner::Http(http) => connect!(http, $dst, $proxy), | ||||||
|                     #[cfg(feature = "default-tls")] |                     #[cfg(feature = "default-tls")] | ||||||
|                     Inner::DefaultTls(http, tls) => { |                     Inner::DefaultTls(http, tls) => { | ||||||
|                         let http = ::hyper_tls::HttpsConnector::from((http.clone(), tls.clone())); |                         let mut http = http.clone(); | ||||||
|  |                         http.set_nodelay(nodelay); | ||||||
|  |                         let http = ::hyper_tls::HttpsConnector::from((http, tls.clone())); | ||||||
|                         connect!(http, $dst, $proxy) |                         connect!(http, $dst, $proxy) | ||||||
|                     }, |                     }, | ||||||
|                     #[cfg(feature = "rustls-tls")] |                     #[cfg(feature = "rustls-tls")] | ||||||
|                     Inner::RustlsTls { http, tls, .. } => { |                     Inner::RustlsTls { http, tls, .. } => { | ||||||
|                         use ::rustls::Session; |  | ||||||
|  |  | ||||||
|                         let mut http = http.clone(); |                         let mut http = http.clone(); | ||||||
|  |  | ||||||
|                         // Disable Nagle's algorithm for TLS handshake |                         // Disable Nagle's algorithm for TLS handshake | ||||||
|                         // |                         // | ||||||
|                         // https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES |                         // https://www.openssl.org/docs/man1.1.1/man3/SSL_connect.html#NOTES | ||||||
|                         if $dst.scheme() == "https" { |                         http.set_nodelay(nodelay || ($dst.scheme() == "https")); | ||||||
|                             http.set_nodelay(true); |  | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                         let http = ::hyper_rustls::HttpsConnector::from((http, tls.clone())); |                         let http = ::hyper_rustls::HttpsConnector::from((http, tls.clone())); | ||||||
|  |  | ||||||
|                         timeout!(http.connect($dst) |                         timeout!(http.connect($dst) | ||||||
|                             .and_then(|(mut io, connected)| { |                             .and_then(move |(io, connected)| { | ||||||
|                                 if let ::hyper_rustls::MaybeHttpsStream::Https(stream) = &mut io { |                                 if let ::hyper_rustls::MaybeHttpsStream::Https(stream) = &io { | ||||||
|                                     let (io, session) = stream.get_mut(); |                                     let (io, _) = stream.get_ref(); | ||||||
|  |  | ||||||
|                                     // keep nodelay for h2 |                                     if !nodelay { | ||||||
|                                     // |  | ||||||
|                                     // https://http2.github.io/faq/#will-i-need-tcp_nodelay-for-my-http2-connections |  | ||||||
|                                     if session.get_alpn_protocol() != Some(b"h2") { |  | ||||||
|                                         io.set_nodelay(false)?; |                                         io.set_nodelay(false)?; | ||||||
|                                     } |                                     } | ||||||
|                                 } |                                 } | ||||||
| @@ -227,7 +231,9 @@ impl Connect for Connector { | |||||||
|  |  | ||||||
|                         let host = dst.host().to_owned(); |                         let host = dst.host().to_owned(); | ||||||
|                         let port = dst.port().unwrap_or(443); |                         let port = dst.port().unwrap_or(443); | ||||||
|                         let http = ::hyper_tls::HttpsConnector::from((http.clone(), tls.clone())); |                         let mut http = http.clone(); | ||||||
|  |                         http.set_nodelay(nodelay); | ||||||
|  |                         let http = ::hyper_tls::HttpsConnector::from((http, tls.clone())); | ||||||
|                         let tls = tls.clone(); |                         let tls = tls.clone(); | ||||||
|                         return timeout!(http.connect(ndst).and_then(move |(conn, connected)| { |                         return timeout!(http.connect(ndst).and_then(move |(conn, connected)| { | ||||||
|                             trace!("tunneling HTTPS over proxy"); |                             trace!("tunneling HTTPS over proxy"); | ||||||
| @@ -247,7 +253,9 @@ impl Connect for Connector { | |||||||
|  |  | ||||||
|                         let host = dst.host().to_owned(); |                         let host = dst.host().to_owned(); | ||||||
|                         let port = dst.port().unwrap_or(443); |                         let port = dst.port().unwrap_or(443); | ||||||
|                         let http = ::hyper_rustls::HttpsConnector::from((http.clone(), tls_proxy.clone())); |                         let mut http = http.clone(); | ||||||
|  |                         http.set_nodelay(nodelay); | ||||||
|  |                         let http = ::hyper_rustls::HttpsConnector::from((http, tls_proxy.clone())); | ||||||
|                         let tls = tls.clone(); |                         let tls = tls.clone(); | ||||||
|                         return timeout!(http.connect(ndst).and_then(move |(conn, connected)| { |                         return timeout!(http.connect(ndst).and_then(move |(conn, connected)| { | ||||||
|                             trace!("tunneling HTTPS over proxy"); |                             trace!("tunneling HTTPS over proxy"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user