Skip to content
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
6 changes: 3 additions & 3 deletions crates/primp-reqwest/src/async_impl/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,10 +792,10 @@ impl ClientBuilder {
));
}

let roots = if config.root_certs.is_empty() {
crate::tls::default_root_store().clone()
let roots: Arc<rustls::RootCertStore> = if config.root_certs.is_empty() {
crate::tls::default_root_store_arc()
} else {
crate::tls::merged_root_store(config.root_certs)?
Arc::new(crate::tls::merged_root_store(config.root_certs)?)
};

config_builder.with_root_certificates(roots)
Expand Down
14 changes: 14 additions & 0 deletions crates/primp-reqwest/src/tls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use rustls_pki_types::{ServerName, UnixTime};
use std::{
fmt,
io::{BufRead, BufReader},
sync::Arc,
};

/// Represents a X509 certificate revocation list.
Expand Down Expand Up @@ -640,6 +641,19 @@ pub fn default_root_store() -> &'static rustls::RootCertStore {
})
}

/// Returns a cached `Arc<RootCertStore>`, avoiding deep clones on every call.
///
/// The underlying store is initialized once (loading webpki + native roots),
/// and subsequent calls only increment the `Arc` reference count.
#[cfg(feature = "__rustls")]
pub fn default_root_store_arc() -> Arc<rustls::RootCertStore> {
static DEFAULT_ROOTS_ARC: std::sync::OnceLock<Arc<rustls::RootCertStore>> =
std::sync::OnceLock::new();
DEFAULT_ROOTS_ARC
.get_or_init(|| Arc::new(default_root_store().clone()))
.clone()
}

/// Creates a root certificate store from the cached default store plus user-provided certs.
#[cfg(feature = "__rustls")]
pub fn merged_root_store(certs: Vec<Certificate>) -> crate::Result<RootCertStore> {
Expand Down
58 changes: 45 additions & 13 deletions crates/primp/src/imp/safari/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ pub(crate) fn build_safari_settings(
};

// Get cached browser emulator for Safari (Arc clone = cheap refcount increment)
let mut browser_emulator = safari_emulator(safari, browser_os);
// Set OS type on our unique clone (cached emulator retains None)
Arc::make_mut(&mut browser_emulator).os_type = Some(browser_os);
let browser_emulator = safari_emulator(safari, browser_os);

let http2 = build_http2_settings();

Expand Down Expand Up @@ -118,16 +116,50 @@ fn build_http2_settings() -> crate::imp::Http2Data {

fn safari_emulator(safari: Impersonate, browser_os: BrowserEmulatorOS) -> Arc<BrowserEmulator> {
match safari {
Impersonate::SafariV18_5 => {
static EMU: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
EMU.get_or_init(|| Arc::new(new_safari_18_5_emulator()))
.clone()
}
Impersonate::SafariV26 => {
static EMU: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
EMU.get_or_init(|| Arc::new(new_safari_26_emulator()))
.clone()
}
Impersonate::SafariV18_5 => match browser_os {
BrowserEmulatorOS::IOS => {
static EMU_IOS: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
EMU_IOS
.get_or_init(|| {
let mut emu = new_safari_18_5_emulator();
emu.os_type = Some(BrowserEmulatorOS::IOS);
Arc::new(emu)
})
.clone()
}
_ => {
static EMU_MACOS: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
EMU_MACOS
.get_or_init(|| {
let mut emu = new_safari_18_5_emulator();
emu.os_type = Some(BrowserEmulatorOS::MacOS);
Arc::new(emu)
})
.clone()
}
},
Impersonate::SafariV26 => match browser_os {
BrowserEmulatorOS::IOS => {
static EMU_IOS: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
EMU_IOS
.get_or_init(|| {
let mut emu = new_safari_26_emulator();
emu.os_type = Some(BrowserEmulatorOS::IOS);
Arc::new(emu)
})
.clone()
}
_ => {
static EMU_MACOS: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
EMU_MACOS
.get_or_init(|| {
let mut emu = new_safari_26_emulator();
emu.os_type = Some(BrowserEmulatorOS::MacOS);
Arc::new(emu)
})
.clone()
}
},
Impersonate::SafariV26_3 => {
if browser_os == BrowserEmulatorOS::IOS {
static EMU_IOS: OnceLock<Arc<BrowserEmulator>> = OnceLock::new();
Expand Down
Loading