1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-30 18:44:35 +01:00

only build SslConnectorBuilder once

fixes #2502
This commit is contained in:
Rob Ede 2021-12-10 23:06:21 +00:00
parent f62383a975
commit 92b8673475
No known key found for this signature in database
GPG Key ID: 97C636207D3EF933
2 changed files with 55 additions and 17 deletions

View File

@ -1,6 +1,9 @@
# Changes # Changes
## Unreleased - 2021-xx-xx ## Unreleased - 2021-xx-xx
* Improve `Client` instantiation efficiency when using `openssl` by only building connectors once. [#2503]
[#2503]: https://github.com/actix/actix-web/pull/2503
## 3.0.0-beta.12 - 2021-11-30 ## 3.0.0-beta.12 - 2021-11-30

View File

@ -22,11 +22,13 @@ use futures_core::{future::LocalBoxFuture, ready};
use http::Uri; use http::Uri;
use pin_project_lite::pin_project; use pin_project_lite::pin_project;
use super::config::ConnectorConfig; use super::{
use super::connection::{Connection, ConnectionIo}; config::ConnectorConfig,
use super::error::ConnectError; connection::{Connection, ConnectionIo},
use super::pool::ConnectionPool; error::ConnectError,
use super::Connect; pool::ConnectionPool,
Connect,
};
enum OurTlsConnector { enum OurTlsConnector {
#[allow(dead_code)] // only dead when no TLS feature is enabled #[allow(dead_code)] // only dead when no TLS feature is enabled
@ -35,6 +37,12 @@ enum OurTlsConnector {
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
Openssl(actix_tls::connect::openssl::reexports::SslConnector), Openssl(actix_tls::connect::openssl::reexports::SslConnector),
/// Provided because building the OpenSSL context on newer versions can be very slow.
/// This prevents unnecessary calls to `.build()` which constructing the client connector.
#[cfg(feature = "openssl")]
#[allow(dead_code)] // false positive; used in build_ssl
OpensslBuilder(tls_openssl::ssl::SslConnectorBuilder),
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
Rustls(std::sync::Arc<actix_tls::connect::rustls::reexports::ClientConfig>), Rustls(std::sync::Arc<actix_tls::connect::rustls::reexports::ClientConfig>),
} }
@ -57,7 +65,7 @@ pub struct Connector<T> {
config: ConnectorConfig, config: ConnectorConfig,
#[allow(dead_code)] // only dead when no TLS feature is enabled #[allow(dead_code)] // only dead when no TLS feature is enabled
ssl: OurTlsConnector, tls: OurTlsConnector,
} }
impl Connector<()> { impl Connector<()> {
@ -69,10 +77,12 @@ impl Connector<()> {
Error = actix_tls::connect::ConnectError, Error = actix_tls::connect::ConnectError,
> + Clone, > + Clone,
> { > {
println!("[awc] Connector::new");
Connector { Connector {
connector: TcpConnector::new(resolver::resolver()).service(), connector: TcpConnector::new(resolver::resolver()).service(),
config: ConnectorConfig::default(), config: ConnectorConfig::default(),
ssl: Self::build_ssl(vec![b"h2".to_vec(), b"http/1.1".to_vec()]), tls: Self::build_ssl(vec![b"h2".to_vec(), b"http/1.1".to_vec()]),
} }
} }
@ -116,7 +126,7 @@ impl Connector<()> {
log::error!("Can not set ALPN protocol: {:?}", err); log::error!("Can not set ALPN protocol: {:?}", err);
} }
OurTlsConnector::Openssl(ssl.build()) OurTlsConnector::OpensslBuilder(ssl)
} }
} }
@ -134,7 +144,7 @@ impl<S> Connector<S> {
Connector { Connector {
connector, connector,
config: self.config, config: self.config,
ssl: self.ssl, tls: self.tls,
} }
} }
} }
@ -167,23 +177,35 @@ where
self self
} }
/// Use custom OpenSSL `SslConnector` instance.
#[cfg(feature = "openssl")] #[cfg(feature = "openssl")]
/// Use custom `SslConnector` instance. pub fn openssl(
mut self,
connector: actix_tls::connect::openssl::reexports::SslConnector,
) -> Self {
self.tls = OurTlsConnector::Openssl(connector);
self
}
/// See docs for [`Connector::openssl`].
#[doc(hidden)]
#[cfg(feature = "openssl")]
#[deprecated(since = "3.0.0", note = "Renamed to `Connector::openssl`.")]
pub fn ssl( pub fn ssl(
mut self, mut self,
connector: actix_tls::connect::openssl::reexports::SslConnector, connector: actix_tls::connect::openssl::reexports::SslConnector,
) -> Self { ) -> Self {
self.ssl = OurTlsConnector::Openssl(connector); self.tls = OurTlsConnector::Openssl(connector);
self self
} }
/// Use custom Rustls `ClientConfig` instance.
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
/// Use custom `ClientConfig` instance.
pub fn rustls( pub fn rustls(
mut self, mut self,
connector: std::sync::Arc<actix_tls::connect::rustls::reexports::ClientConfig>, connector: std::sync::Arc<actix_tls::connect::rustls::reexports::ClientConfig>,
) -> Self { ) -> Self {
self.ssl = OurTlsConnector::Rustls(connector); self.tls = OurTlsConnector::Rustls(connector);
self self
} }
@ -198,7 +220,8 @@ where
unimplemented!("actix-http client only supports versions http/1.1 & http/2") unimplemented!("actix-http client only supports versions http/1.1 & http/2")
} }
}; };
self.ssl = Connector::build_ssl(versions); println!("[awc] max_http_version");
self.tls = Connector::build_ssl(versions);
self self
} }
@ -270,8 +293,8 @@ where
} }
/// Finish configuration process and create connector service. /// Finish configuration process and create connector service.
/// The Connector builder always concludes by calling `finish()` last in ///
/// its combinator chain. /// The `Connector` builder always concludes by calling `finish()` last in its combinator chain.
pub fn finish(self) -> ConnectorService<S, IO> { pub fn finish(self) -> ConnectorService<S, IO> {
let local_address = self.config.local_address; let local_address = self.config.local_address;
let timeout = self.config.timeout; let timeout = self.config.timeout;
@ -284,7 +307,14 @@ where
service: tcp_service_inner.clone(), service: tcp_service_inner.clone(),
}; };
let tls_service = match self.ssl { let tls = match self.tls {
OurTlsConnector::OpensslBuilder(builder) => {
OurTlsConnector::Openssl(builder.build())
}
tls => tls,
};
let tls_service = match tls {
OurTlsConnector::None => { OurTlsConnector::None => {
#[cfg(not(feature = "dangerous-h2c"))] #[cfg(not(feature = "dangerous-h2c"))]
{ {
@ -374,6 +404,11 @@ where
Some(actix_service::boxed::rc_service(tls_service)) Some(actix_service::boxed::rc_service(tls_service))
} }
#[cfg(feature = "openssl")]
OurTlsConnector::OpensslBuilder(_) => {
unreachable!("OpenSSL builder is built before this match.");
}
#[cfg(feature = "rustls")] #[cfg(feature = "rustls")]
OurTlsConnector::Rustls(tls) => { OurTlsConnector::Rustls(tls) => {
const H2: &[u8] = b"h2"; const H2: &[u8] = b"h2";