Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tls): Reuse https connector layer #107

Merged
merged 3 commits into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Cargo.lock
.direnv
result
curl
.idea
.idea
examples
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ repository = "https://github.com/0x676e67/rquest"
documentation = "https://docs.rs/rquest"
authors = ["0x676e67 <[email protected]>"]
readme = "README.md"
license = "MIT"
license = "Apache-2.0"
edition = "2021"
rust-version = "1.80"
autotests = true
Expand Down Expand Up @@ -100,7 +100,7 @@ hyper = { package = "hyper_imp", version = "0.14", default-features = false, fea
"client",
"runtime",
] }
h2 = { package = "h2_imp", version = "0.5.6" }
h2 = { package = "h2_imp", version = "0.5" }
log = "0.4"
mime = "0.3.17"
percent-encoding = "2.3"
Expand Down
4 changes: 0 additions & 4 deletions src/tls/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ impl Extension for ChromeExtension {
];

let mut builder = SslConnector::builder(SslMethod::tls_client())?;
builder.set_default_verify_paths()?;
builder.set_grease_enabled(true);
builder.enable_ocsp_stapling();
builder.set_curves(&[SslCurve::X25519, SslCurve::SECP256R1, SslCurve::SECP384R1])?;
Expand Down Expand Up @@ -122,7 +121,6 @@ impl Extension for EdgeExtension {
];

let mut builder = SslConnector::builder(SslMethod::tls_client())?;
builder.set_default_verify_paths()?;
builder.set_grease_enabled(true);
builder.enable_ocsp_stapling();
builder.set_curves(&[SslCurve::X25519, SslCurve::SECP256R1, SslCurve::SECP384R1])?;
Expand Down Expand Up @@ -158,7 +156,6 @@ impl Extension for SafariExtension {
];

let mut builder = SslConnector::builder(SslMethod::tls_client())?;
builder.set_default_verify_paths()?;
builder.set_options(SslOptions::NO_TICKET);
builder.set_grease_enabled(true);
builder.enable_ocsp_stapling();
Expand Down Expand Up @@ -197,7 +194,6 @@ impl Extension for OkHttpExtension {
];

let mut builder = SslConnector::builder(SslMethod::tls_client())?;
builder.set_default_verify_paths()?;
builder.enable_ocsp_stapling();
builder.set_curves(&[SslCurve::X25519, SslCurve::SECP256R1, SslCurve::SECP384R1])?;
builder.set_sigalgs_list(&SIGALGS_LIST.join(":"))?;
Expand Down
82 changes: 42 additions & 40 deletions src/tls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use boring::{
error::ErrorStack,
ssl::{ConnectConfiguration, SslConnectorBuilder},
};
use hyper_boring::{HttpsConnector, HttpsLayerSettings, SessionCache};
use hyper_boring::{HttpsConnector, HttpsLayer, HttpsLayerSettings, SessionCache};
use profile::ClientProfile;
pub use profile::{ConnectSettings, Http2Settings, Impersonate};
use std::any::Any;
Expand All @@ -35,12 +35,12 @@ use tokio::sync::OnceCell;
/// Default session cache capacity.
const DEFAULT_SESSION_CACHE_CAPACITY: usize = 8;

/// A builder for a `SslConnectorBuilder`.
pub type Builder = dyn Fn() -> Result<SslConnectorBuilder, ErrorStack> + Send + Sync + 'static;

/// A TLS session cache.
type Session = Arc<Mutex<SessionCache>>;

/// A TLS connector builder.
type Builder = dyn Fn() -> Result<SslConnectorBuilder, ErrorStack> + Send + Sync + 'static;

/// The TLS connector configuration.
#[derive(Clone)]
pub struct TlsConnectorBuilder {
Expand Down Expand Up @@ -100,17 +100,17 @@ impl Debug for TlsConnectorBuilder {
#[derive(Clone)]
pub struct TlsConnector {
/// The inner `SslConnectorBuilder`.
tls_connector: TlsConnectorBuilder,
/// The cached `HttpsConnector` sessions.
session: Arc<OnceCell<Session>>,
builder: TlsConnectorBuilder,
/// The TLS connector layer.
inner: Arc<OnceCell<HttpsLayer>>,
}

impl TlsConnector {
/// Create a new `BoringTlsConnector` with the given function.
pub fn new(tls_connector: TlsConnectorBuilder) -> TlsConnector {
pub fn new(builder: TlsConnectorBuilder) -> TlsConnector {
Self {
tls_connector,
session: Arc::new(OnceCell::new()),
builder,
inner: Arc::new(OnceCell::new()),
}
}

Expand All @@ -120,7 +120,28 @@ impl TlsConnector {
&self,
http: HttpConnector,
) -> Result<HttpsConnector<HttpConnector>, ErrorStack> {
let tls = &self.tls_connector;
// Get the `HttpsLayer` or create it if it doesn't exist.
let layer = self
.inner
.get_or_try_init(|| async { self.build_layer().await })
.await
.map(Clone::clone)?;

// Create the `HttpsConnector` with the given `HttpConnector` and `HttpsLayer`.
let mut http = HttpsConnector::with_connector_layer(http, layer);

// Set the callback to add application settings.
let builder = self.builder.clone();
http.set_callback(move |conf, _| {
configure_ssl_context(conf, &builder);
Ok(())
});

Ok(http)
}

async fn build_layer(&self) -> Result<HttpsLayer, ErrorStack> {
let tls = &self.builder;
// Create the `SslConnectorBuilder` and configure it.
let builder = (tls.builder)()?
.configure_alpn_protos(&tls.http_version_pref)?
Expand All @@ -142,38 +163,19 @@ impl TlsConnector {
| Impersonate::Edge127
);

// Create the `HttpsConnector` with the given settings.
let mut http = if psk_extension || tls.pre_shared_key {
// Initialize the session cache.
let session = self
.session
.get_or_init(|| async {
Session::new(Mutex::new(SessionCache::with_capacity(
DEFAULT_SESSION_CACHE_CAPACITY,
)))
})
.await
.clone();

HttpsConnector::with_connector_and_settings(
http,
if psk_extension || tls.pre_shared_key {
HttpsLayer::with_connector_and_settings(
builder,
HttpsLayerSettings::builder()
.session_cache_capacity(DEFAULT_SESSION_CACHE_CAPACITY)
.session_cache(session)
.session_cache(Session::new(Mutex::new(SessionCache::with_capacity(
DEFAULT_SESSION_CACHE_CAPACITY,
))))
.build(),
)?
)
} else {
HttpsConnector::with_connector(http, builder)?
};

// Set the callback to add application settings.
let context = tls.clone();
http.set_callback(move |conf, _| {
configure_ssl_context(conf, &context);
Ok(())
});
Ok(http)
HttpsLayer::with_connector(builder)
}
}
}

Expand All @@ -192,8 +194,8 @@ fn configure_ssl_context(conf: &mut ConnectConfiguration, ctx: &TlsConnectorBuil
impl Debug for TlsConnector {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BoringTlsConnector")
.field("builder", &self.tls_connector.type_id())
.field("session", &self.session.type_id())
.field("builder", &self.builder.type_id())
.field("connector", &self.type_id())
.finish()
}
}
Expand Down
Loading