summaryrefslogtreecommitdiff
path: root/cli
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2023-05-01 16:42:05 -0400
committerGitHub <noreply@github.com>2023-05-01 16:42:05 -0400
commit913176313b6869eeb29b8d48e0c8d80227fa6544 (patch)
treecc0128b36ea9b22207a3dd41a401ae4ecd131e74 /cli
parentecc70eb58fd5531f3b93402cf781e93ef2bb4d64 (diff)
perf: lazily create RootCertStore (#18938)
Diffstat (limited to 'cli')
-rw-r--r--cli/args/mod.rs73
-rw-r--r--cli/factory.rs34
-rw-r--r--cli/file_fetcher.rs39
-rw-r--r--cli/http_util.rs72
-rw-r--r--cli/lsp/language_server.rs33
-rw-r--r--cli/lsp/registries.rs32
-rw-r--r--cli/npm/cache.rs5
-rw-r--r--cli/npm/registry.rs4
-rw-r--r--cli/standalone/mod.rs35
-rw-r--r--cli/tools/installer.rs2
-rw-r--r--cli/tools/run.rs2
-rw-r--r--cli/tools/standalone.rs2
-rw-r--r--cli/tools/upgrade.rs12
-rw-r--r--cli/worker.rs14
14 files changed, 241 insertions, 118 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 00476dce1..b5975536a 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -13,6 +13,7 @@ use self::package_json::PackageJsonDeps;
use ::import_map::ImportMap;
use deno_core::resolve_url_or_path;
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
+use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_semver::npm::NpmPackageReqReference;
use indexmap::IndexMap;
@@ -52,6 +53,7 @@ use deno_runtime::deno_tls::webpki_roots;
use deno_runtime::inspector_server::InspectorServer;
use deno_runtime::permissions::PermissionsOptions;
use once_cell::sync::Lazy;
+use once_cell::sync::OnceCell;
use std::collections::HashMap;
use std::env;
use std::io::BufReader;
@@ -61,6 +63,7 @@ use std::num::NonZeroUsize;
use std::path::Path;
use std::path::PathBuf;
use std::sync::Arc;
+use thiserror::Error;
use crate::cache::DenoDir;
use crate::file_fetcher::FileFetcher;
@@ -401,13 +404,62 @@ fn discover_package_json(
Ok(None)
}
+struct CliRootCertStoreProvider {
+ cell: OnceCell<RootCertStore>,
+ maybe_root_path: Option<PathBuf>,
+ maybe_ca_stores: Option<Vec<String>>,
+ maybe_ca_data: Option<CaData>,
+}
+
+impl CliRootCertStoreProvider {
+ pub fn new(
+ maybe_root_path: Option<PathBuf>,
+ maybe_ca_stores: Option<Vec<String>>,
+ maybe_ca_data: Option<CaData>,
+ ) -> Self {
+ Self {
+ cell: Default::default(),
+ maybe_root_path,
+ maybe_ca_stores,
+ maybe_ca_data,
+ }
+ }
+}
+
+impl RootCertStoreProvider for CliRootCertStoreProvider {
+ fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> {
+ self
+ .cell
+ .get_or_try_init(|| {
+ get_root_cert_store(
+ self.maybe_root_path.clone(),
+ self.maybe_ca_stores.clone(),
+ self.maybe_ca_data.clone(),
+ )
+ })
+ .map_err(|e| e.into())
+ }
+}
+
+#[derive(Error, Debug, Clone)]
+pub enum RootCertStoreLoadError {
+ #[error(
+ "Unknown certificate store \"{0}\" specified (allowed: \"system,mozilla\")"
+ )]
+ UnknownStore(String),
+ #[error("Unable to add pem file to certificate store: {0}")]
+ FailedAddPemFile(String),
+ #[error("Failed opening CA file: {0}")]
+ CaFileOpenError(String),
+}
+
/// Create and populate a root cert store based on the passed options and
/// environment.
pub fn get_root_cert_store(
maybe_root_path: Option<PathBuf>,
maybe_ca_stores: Option<Vec<String>>,
maybe_ca_data: Option<CaData>,
-) -> Result<RootCertStore, AnyError> {
+) -> Result<RootCertStore, RootCertStoreLoadError> {
let mut root_cert_store = RootCertStore::empty();
let ca_stores: Vec<String> = maybe_ca_stores
.or_else(|| {
@@ -444,7 +496,7 @@ pub fn get_root_cert_store(
}
}
_ => {
- return Err(anyhow!("Unknown certificate store \"{}\" specified (allowed: \"system,mozilla\")", store));
+ return Err(RootCertStoreLoadError::UnknownStore(store.clone()));
}
}
}
@@ -459,7 +511,9 @@ pub fn get_root_cert_store(
} else {
PathBuf::from(ca_file)
};
- let certfile = std::fs::File::open(ca_file)?;
+ let certfile = std::fs::File::open(ca_file).map_err(|err| {
+ RootCertStoreLoadError::CaFileOpenError(err.to_string())
+ })?;
let mut reader = BufReader::new(certfile);
rustls_pemfile::certs(&mut reader)
}
@@ -474,10 +528,7 @@ pub fn get_root_cert_store(
root_cert_store.add_parsable_certificates(&certs);
}
Err(e) => {
- return Err(anyhow!(
- "Unable to add pem file to certificate store: {}",
- e
- ));
+ return Err(RootCertStoreLoadError::FailedAddPemFile(e.to_string()));
}
}
}
@@ -799,12 +850,14 @@ impl CliOptions {
.map(|path| ModuleSpecifier::from_directory_path(path).unwrap())
}
- pub fn resolve_root_cert_store(&self) -> Result<RootCertStore, AnyError> {
- get_root_cert_store(
+ pub fn resolve_root_cert_store_provider(
+ &self,
+ ) -> Arc<dyn RootCertStoreProvider> {
+ Arc::new(CliRootCertStoreProvider::new(
None,
self.flags.ca_stores.clone(),
self.flags.ca_data.clone(),
- )
+ ))
}
pub fn resolve_ts_config_for_emit(
diff --git a/cli/factory.rs b/cli/factory.rs
index 69560cf54..73d0cb8ea 100644
--- a/cli/factory.rs
+++ b/cli/factory.rs
@@ -45,7 +45,7 @@ use deno_core::parking_lot::Mutex;
use deno_runtime::deno_node;
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
use deno_runtime::deno_node::NodeResolver;
-use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::inspector_server::InspectorServer;
use deno_semver::npm::NpmPackageReqReference;
@@ -129,14 +129,14 @@ struct CliFactoryServices {
dir: Deferred<DenoDir>,
caches: Deferred<Arc<Caches>>,
file_fetcher: Deferred<Arc<FileFetcher>>,
- http_client: Deferred<HttpClient>,
+ http_client: Deferred<Arc<HttpClient>>,
emit_cache: Deferred<EmitCache>,
emitter: Deferred<Arc<Emitter>>,
graph_container: Deferred<Arc<ModuleGraphContainer>>,
lockfile: Deferred<Option<Arc<Mutex<Lockfile>>>>,
maybe_import_map: Deferred<Option<Arc<ImportMap>>>,
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
- root_cert_store: Deferred<RootCertStore>,
+ root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
blob_store: Deferred<BlobStore>,
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
resolver: Deferred<Arc<CliGraphResolver>>,
@@ -208,11 +208,11 @@ impl CliFactory {
self.services.blob_store.get_or_init(BlobStore::default)
}
- pub fn root_cert_store(&self) -> Result<&RootCertStore, AnyError> {
+ pub fn root_cert_store_provider(&self) -> &Arc<dyn RootCertStoreProvider> {
self
.services
- .root_cert_store
- .get_or_try_init(|| self.options.resolve_root_cert_store())
+ .root_cert_store_provider
+ .get_or_init(|| self.options.resolve_root_cert_store_provider())
}
pub fn text_only_progress_bar(&self) -> &ProgressBar {
@@ -222,12 +222,12 @@ impl CliFactory {
.get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly))
}
- pub fn http_client(&self) -> Result<&HttpClient, AnyError> {
- self.services.http_client.get_or_try_init(|| {
- HttpClient::new(
- Some(self.root_cert_store()?.clone()),
+ pub fn http_client(&self) -> &Arc<HttpClient> {
+ self.services.http_client.get_or_init(|| {
+ Arc::new(HttpClient::new(
+ Some(self.root_cert_store_provider().clone()),
self.options.unsafely_ignore_certificate_errors().clone(),
- )
+ ))
})
}
@@ -237,7 +237,7 @@ impl CliFactory {
HttpCache::new(&self.deno_dir()?.deps_folder_path()),
self.options.cache_setting(),
!self.options.no_remote(),
- self.http_client()?.clone(),
+ self.http_client().clone(),
self.blob_store().clone(),
Some(self.text_only_progress_bar().clone()),
)))
@@ -256,7 +256,7 @@ impl CliFactory {
Ok(Arc::new(NpmCache::new(
self.deno_dir()?.npm_folder_path(),
self.options.cache_setting(),
- self.http_client()?.clone(),
+ self.http_client().clone(),
self.text_only_progress_bar().clone(),
)))
})
@@ -267,7 +267,7 @@ impl CliFactory {
Ok(Arc::new(CliNpmRegistryApi::new(
CliNpmRegistryApi::default_url().to_owned(),
self.npm_cache()?.clone(),
- self.http_client()?.clone(),
+ self.http_client().clone(),
self.text_only_progress_bar().clone(),
)))
})
@@ -554,7 +554,7 @@ impl CliFactory {
let options = self.cli_options().clone();
let main_worker_options = self.create_cli_main_worker_options()?;
let node_fs = self.node_fs().clone();
- let root_cert_store = self.root_cert_store()?.clone();
+ let root_cert_store_provider = self.root_cert_store_provider().clone();
let node_resolver = self.node_resolver().await?.clone();
let npm_resolver = self.npm_resolver().await?.clone();
let maybe_inspector_server = self.maybe_inspector_server().clone();
@@ -578,7 +578,7 @@ impl CliFactory {
node_resolver.clone(),
),
)),
- root_cert_store.clone(),
+ root_cert_store_provider.clone(),
node_fs.clone(),
maybe_inspector_server.clone(),
main_worker_options.clone(),
@@ -609,7 +609,7 @@ impl CliFactory {
node_resolver.clone(),
),
)),
- self.root_cert_store()?.clone(),
+ self.root_cert_store_provider().clone(),
self.node_fs().clone(),
self.maybe_inspector_server().clone(),
self.create_cli_main_worker_options()?,
diff --git a/cli/file_fetcher.rs b/cli/file_fetcher.rs
index 38b96c72d..fd8c0f793 100644
--- a/cli/file_fetcher.rs
+++ b/cli/file_fetcher.rs
@@ -178,7 +178,7 @@ pub struct FileFetcher {
cache: FileCache,
cache_setting: CacheSetting,
pub http_cache: HttpCache,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
blob_store: BlobStore,
download_log_level: log::Level,
progress_bar: Option<ProgressBar>,
@@ -189,7 +189,7 @@ impl FileFetcher {
http_cache: HttpCache,
cache_setting: CacheSetting,
allow_remote: bool,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
blob_store: BlobStore,
progress_bar: Option<ProgressBar>,
) -> Self {
@@ -660,7 +660,7 @@ async fn fetch_once<'a>(
http_client: &HttpClient,
args: FetchOnceArgs<'a>,
) -> Result<FetchOnceResult, AnyError> {
- let mut request = http_client.get_no_redirect(args.url.clone());
+ let mut request = http_client.get_no_redirect(args.url.clone())?;
if let Some(etag) = args.maybe_etag {
let if_none_match_val = HeaderValue::from_str(&etag)?;
@@ -769,7 +769,7 @@ mod tests {
HttpCache::new(&location),
cache_setting,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
blob_store.clone(),
None,
);
@@ -1207,7 +1207,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::ReloadAll,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1232,7 +1232,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Use,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1257,7 +1257,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Use,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1398,7 +1398,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Use,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1426,7 +1426,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Use,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1525,7 +1525,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Use,
false,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1550,7 +1550,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Only,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -1558,7 +1558,7 @@ mod tests {
HttpCache::new(&location),
CacheSetting::Use,
true,
- HttpClient::new(None, None).unwrap(),
+ Arc::new(HttpClient::new(None, None)),
BlobStore::default(),
None,
);
@@ -2021,15 +2021,24 @@ mod tests {
#[ignore] // https://github.com/denoland/deno/issues/12561
async fn test_fetch_with_empty_certificate_store() {
use deno_runtime::deno_tls::rustls::RootCertStore;
+ use deno_runtime::deno_tls::RootCertStoreProvider;
+
+ struct ValueRootCertStoreProvider(RootCertStore);
+
+ impl RootCertStoreProvider for ValueRootCertStoreProvider {
+ fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> {
+ Ok(&self.0)
+ }
+ }
let _http_server_guard = test_util::http_server();
// Relies on external http server with a valid mozilla root CA cert.
let url = Url::parse("https://deno.land").unwrap();
let client = HttpClient::new(
- Some(RootCertStore::empty()), // no certs loaded at all
+ // no certs loaded at all
+ Some(Arc::new(ValueRootCertStoreProvider(RootCertStore::empty()))),
None,
- )
- .unwrap();
+ );
let result = fetch_once(
&client,
diff --git a/cli/http_util.rs b/cli/http_util.rs
index b01732ca9..7c17e8e1e 100644
--- a/cli/http_util.rs
+++ b/cli/http_util.rs
@@ -15,8 +15,9 @@ use deno_runtime::deno_fetch::create_http_client;
use deno_runtime::deno_fetch::reqwest;
use deno_runtime::deno_fetch::reqwest::header::LOCATION;
use deno_runtime::deno_fetch::reqwest::Response;
-use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_tls::RootCertStoreProvider;
use std::collections::HashMap;
+use std::sync::Arc;
use std::time::Duration;
use std::time::SystemTime;
@@ -217,34 +218,68 @@ impl CacheSemantics {
}
}
-#[derive(Debug, Clone)]
-pub struct HttpClient(reqwest::Client);
+pub struct HttpClient {
+ root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
+ unsafely_ignore_certificate_errors: Option<Vec<String>>,
+ cell: once_cell::sync::OnceCell<reqwest::Client>,
+}
+
+impl std::fmt::Debug for HttpClient {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("HttpClient")
+ .field(
+ "unsafely_ignore_certificate_errors",
+ &self.unsafely_ignore_certificate_errors,
+ )
+ .finish()
+ }
+}
impl HttpClient {
pub fn new(
- root_cert_store: Option<RootCertStore>,
+ root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
unsafely_ignore_certificate_errors: Option<Vec<String>>,
- ) -> Result<Self, AnyError> {
- Ok(HttpClient::from_client(create_http_client(
- get_user_agent(),
- root_cert_store,
- vec![],
- None,
+ ) -> Self {
+ Self {
+ root_cert_store_provider,
unsafely_ignore_certificate_errors,
- None,
- )?))
+ cell: Default::default(),
+ }
}
+ #[cfg(test)]
pub fn from_client(client: reqwest::Client) -> Self {
- Self(client)
+ let result = Self {
+ root_cert_store_provider: Default::default(),
+ unsafely_ignore_certificate_errors: Default::default(),
+ cell: Default::default(),
+ };
+ result.cell.set(client).unwrap();
+ result
+ }
+
+ fn client(&self) -> Result<&reqwest::Client, AnyError> {
+ self.cell.get_or_try_init(|| {
+ create_http_client(
+ get_user_agent(),
+ match &self.root_cert_store_provider {
+ Some(provider) => Some(provider.get_or_try_init()?.clone()),
+ None => None,
+ },
+ vec![],
+ None,
+ self.unsafely_ignore_certificate_errors.clone(),
+ None,
+ )
+ })
}
/// Do a GET request without following redirects.
pub fn get_no_redirect<U: reqwest::IntoUrl>(
&self,
url: U,
- ) -> reqwest::RequestBuilder {
- self.0.get(url)
+ ) -> Result<reqwest::RequestBuilder, AnyError> {
+ Ok(self.client()?.get(url))
}
pub async fn download_text<U: reqwest::IntoUrl>(
@@ -306,12 +341,13 @@ impl HttpClient {
url: U,
) -> Result<Response, AnyError> {
let mut url = url.into_url()?;
- let mut response = self.get_no_redirect(url.clone()).send().await?;
+ let mut response = self.get_no_redirect(url.clone())?.send().await?;
let status = response.status();
if status.is_redirection() {
for _ in 0..5 {
let new_url = resolve_redirect_from_response(&url, &response)?;
- let new_response = self.get_no_redirect(new_url.clone()).send().await?;
+ let new_response =
+ self.get_no_redirect(new_url.clone())?.send().await?;
let status = new_response.status();
if status.is_redirection() {
response = new_response;
@@ -357,7 +393,7 @@ mod test {
#[tokio::test]
async fn test_http_client_download_redirect() {
let _http_server_guard = test_util::http_server();
- let client = HttpClient::new(None, None).unwrap();
+ let client = HttpClient::new(None, None);
// make a request to the redirect server
let text = client
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index d49a2559c..83657a8ef 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -12,6 +12,8 @@ use deno_core::ModuleSpecifier;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJson;
+use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use import_map::ImportMap;
use log::error;
@@ -93,6 +95,14 @@ use crate::util::path::specifier_to_file_path;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
+struct LspRootCertStoreProvider(RootCertStore);
+
+impl RootCertStoreProvider for LspRootCertStoreProvider {
+ fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> {
+ Ok(&self.0)
+ }
+}
+
#[derive(Debug, Clone)]
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
@@ -124,7 +134,7 @@ pub struct Inner {
/// The collection of documents that the server is currently handling, either
/// on disk or "open" within the client.
pub documents: Documents,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
/// Handles module registries, which allow discovery of modules
module_registries: ModuleRegistry,
/// The path to the module registries cache
@@ -420,7 +430,7 @@ impl LanguageServer {
fn create_lsp_structs(
dir: &DenoDir,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
) -> (
Arc<CliNpmRegistryApi>,
Arc<NpmCache>,
@@ -469,10 +479,9 @@ impl Inner {
let dir =
DenoDir::new(maybe_custom_root).expect("could not access DENO_DIR");
let module_registries_location = dir.registries_folder_path();
- let http_client = HttpClient::new(None, None).unwrap();
+ let http_client = Arc::new(HttpClient::new(None, None));
let module_registries =
- ModuleRegistry::new(&module_registries_location, http_client.clone())
- .unwrap();
+ ModuleRegistry::new(&module_registries_location, http_client.clone());
let location = dir.deps_folder_path();
let documents = Documents::new(&location, client.kind());
let deps_http_cache = HttpCache::new(&location);
@@ -775,20 +784,22 @@ impl Inner {
.root_uri
.as_ref()
.and_then(|uri| specifier_to_file_path(uri).ok());
- let root_cert_store = Some(get_root_cert_store(
+ let root_cert_store = get_root_cert_store(
maybe_root_path,
workspace_settings.certificate_stores,
workspace_settings.tls_certificate.map(CaData::File),
- )?);
+ )?;
+ let root_cert_store_provider =
+ Arc::new(LspRootCertStoreProvider(root_cert_store));
let module_registries_location = dir.registries_folder_path();
- self.http_client = HttpClient::new(
- root_cert_store,
+ self.http_client = Arc::new(HttpClient::new(
+ Some(root_cert_store_provider),
workspace_settings.unsafely_ignore_certificate_errors,
- )?;
+ ));
self.module_registries = ModuleRegistry::new(
&module_registries_location,
self.http_client.clone(),
- )?;
+ );
self.module_registries_location = module_registries_location;
(
self.npm_api,
diff --git a/cli/lsp/registries.rs b/cli/lsp/registries.rs
index f46aba44f..b2f9bee2c 100644
--- a/cli/lsp/registries.rs
+++ b/cli/lsp/registries.rs
@@ -35,6 +35,7 @@ use log::error;
use once_cell::sync::Lazy;
use std::collections::HashMap;
use std::path::Path;
+use std::sync::Arc;
use tower_lsp::lsp_types as lsp;
const CONFIG_PATH: &str = "/.well-known/deno-import-intellisense.json";
@@ -425,16 +426,13 @@ impl Default for ModuleRegistry {
// custom root.
let dir = DenoDir::new(None).unwrap();
let location = dir.registries_folder_path();
- let http_client = HttpClient::new(None, None).unwrap();
- Self::new(&location, http_client).unwrap()
+ let http_client = Arc::new(HttpClient::new(None, None));
+ Self::new(&location, http_client)
}
}
impl ModuleRegistry {
- pub fn new(
- location: &Path,
- http_client: HttpClient,
- ) -> Result<Self, AnyError> {
+ pub fn new(location: &Path, http_client: Arc<HttpClient>) -> Self {
let http_cache = HttpCache::new(location);
let mut file_fetcher = FileFetcher::new(
http_cache,
@@ -446,10 +444,10 @@ impl ModuleRegistry {
);
file_fetcher.set_download_log_level(super::logging::lsp_log_level());
- Ok(Self {
+ Self {
origins: HashMap::new(),
file_fetcher,
- })
+ }
}
fn complete_literal(
@@ -1251,8 +1249,7 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("registries");
let mut module_registry =
- ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
- .unwrap();
+ ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
module_registry
.enable("http://localhost:4545/")
.await
@@ -1313,8 +1310,7 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("registries");
let mut module_registry =
- ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
- .unwrap();
+ ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
module_registry
.enable("http://localhost:4545/")
.await
@@ -1537,8 +1533,7 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("registries");
let mut module_registry =
- ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
- .unwrap();
+ ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
module_registry
.enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-key-first.json")
.await
@@ -1608,8 +1603,7 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("registries");
let mut module_registry =
- ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
- .unwrap();
+ ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
module_registry
.enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-complex.json")
.await
@@ -1660,8 +1654,7 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("registries");
let module_registry =
- ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
- .unwrap();
+ ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
let result = module_registry.check_origin("http://localhost:4545").await;
assert!(result.is_ok());
}
@@ -1672,8 +1665,7 @@ mod tests {
let temp_dir = TempDir::new();
let location = temp_dir.path().join("registries");
let module_registry =
- ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
- .unwrap();
+ ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
let result = module_registry.check_origin("https://example.com").await;
assert!(result.is_err());
let err = result.unwrap_err().to_string();
diff --git a/cli/npm/cache.rs b/cli/npm/cache.rs
index 0d88109de..cda40fd17 100644
--- a/cli/npm/cache.rs
+++ b/cli/npm/cache.rs
@@ -4,6 +4,7 @@ use std::collections::HashSet;
use std::fs;
use std::path::Path;
use std::path::PathBuf;
+use std::sync::Arc;
use deno_ast::ModuleSpecifier;
use deno_core::anyhow::bail;
@@ -295,7 +296,7 @@ impl ReadonlyNpmCache {
pub struct NpmCache {
readonly: ReadonlyNpmCache,
cache_setting: CacheSetting,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
progress_bar: ProgressBar,
/// ensures a package is only downloaded once per run
previously_reloaded_packages: Mutex<HashSet<NpmPackageNv>>,
@@ -305,7 +306,7 @@ impl NpmCache {
pub fn new(
cache_dir_path: PathBuf,
cache_setting: CacheSetting,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
progress_bar: ProgressBar,
) -> Self {
Self {
diff --git a/cli/npm/registry.rs b/cli/npm/registry.rs
index ef050a734..40d7f6219 100644
--- a/cli/npm/registry.rs
+++ b/cli/npm/registry.rs
@@ -63,7 +63,7 @@ impl CliNpmRegistryApi {
pub fn new(
base_url: Url,
cache: Arc<NpmCache>,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
progress_bar: ProgressBar,
) -> Self {
Self(Some(Arc::new(CliNpmRegistryApiInner {
@@ -172,7 +172,7 @@ struct CliNpmRegistryApiInner {
force_reload_flag: AtomicFlag,
mem_cache: Mutex<HashMap<String, CacheItem>>,
previously_reloaded_packages: Mutex<HashSet<String>>,
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
progress_bar: ProgressBar,
}
diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs
index 556346535..2ef21d417 100644
--- a/cli/standalone/mod.rs
+++ b/cli/standalone/mod.rs
@@ -32,6 +32,8 @@ use deno_core::ResolutionKind;
use deno_graph::source::Resolver;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolver;
+use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::permissions::Permissions;
use deno_runtime::permissions::PermissionsContainer;
@@ -161,22 +163,37 @@ impl HasNodeSpecifierChecker for StandaloneHasNodeSpecifierChecker {
}
}
+struct StandaloneRootCertStoreProvider {
+ ca_stores: Option<Vec<String>>,
+ ca_data: Option<CaData>,
+ cell: once_cell::sync::OnceCell<RootCertStore>,
+}
+
+impl RootCertStoreProvider for StandaloneRootCertStoreProvider {
+ fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError> {
+ self.cell.get_or_try_init(|| {
+ get_root_cert_store(None, self.ca_stores.clone(), self.ca_data.clone())
+ .map_err(|err| err.into())
+ })
+ }
+}
+
pub async fn run(
eszip: eszip::EszipV2,
metadata: Metadata,
) -> Result<(), AnyError> {
let main_module = &metadata.entrypoint;
let dir = DenoDir::new(None)?;
- let root_cert_store = get_root_cert_store(
- None,
- metadata.ca_stores,
- metadata.ca_data.map(CaData::Bytes),
- )?;
+ let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider {
+ ca_stores: metadata.ca_stores,
+ ca_data: metadata.ca_data.map(CaData::Bytes),
+ cell: Default::default(),
+ });
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
- let http_client = HttpClient::new(
- Some(root_cert_store.clone()),
+ let http_client = Arc::new(HttpClient::new(
+ Some(root_cert_store_provider.clone()),
metadata.unsafely_ignore_certificate_errors.clone(),
- )?;
+ ));
let npm_registry_url = CliNpmRegistryApi::default_url().to_owned();
let npm_cache = Arc::new(NpmCache::new(
dir.npm_folder_path(),
@@ -235,7 +252,7 @@ pub async fn run(
Box::new(StandaloneHasNodeSpecifierChecker),
BlobStore::default(),
Box::new(module_loader_factory),
- root_cert_store,
+ root_cert_store_provider,
node_fs,
None,
CliMainWorkerOptions {
diff --git a/cli/tools/installer.rs b/cli/tools/installer.rs
index fb83c3cab..07606d5f8 100644
--- a/cli/tools/installer.rs
+++ b/cli/tools/installer.rs
@@ -133,7 +133,7 @@ pub async fn infer_name_from_url(url: &Url) -> Option<String> {
let mut url = url.clone();
if url.path() == "/" {
- let client = HttpClient::new(None, None).unwrap();
+ let client = HttpClient::new(None, None);
if let Ok(res) = client.get_redirected_response(url.clone()).await {
url = res.url().clone();
}
diff --git a/cli/tools/run.rs b/cli/tools/run.rs
index c6e706285..99312d5b9 100644
--- a/cli/tools/run.rs
+++ b/cli/tools/run.rs
@@ -35,7 +35,7 @@ To grant permissions, set them before the script argument. For example:
// map specified and bare specifier is used on the command line
let factory = CliFactory::from_flags(flags).await?;
let deno_dir = factory.deno_dir()?;
- let http_client = factory.http_client()?;
+ let http_client = factory.http_client();
let cli_options = factory.cli_options();
// Run a background task that checks for available upgrades. If an earlier
diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs
index 0e8d9ca73..d34e5da83 100644
--- a/cli/tools/standalone.rs
+++ b/cli/tools/standalone.rs
@@ -26,7 +26,7 @@ pub async fn compile(
let factory = CliFactory::from_flags(flags).await?;
let cli_options = factory.cli_options();
let file_fetcher = factory.file_fetcher()?;
- let http_client = factory.http_client()?;
+ let http_client = factory.http_client();
let deno_dir = factory.deno_dir()?;
let module_graph_builder = factory.module_graph_builder().await?;
let parsed_source_cache = factory.parsed_source_cache()?;
diff --git a/cli/tools/upgrade.rs b/cli/tools/upgrade.rs
index c76d36777..b5aefe479 100644
--- a/cli/tools/upgrade.rs
+++ b/cli/tools/upgrade.rs
@@ -26,6 +26,7 @@ use std::ops::Sub;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
+use std::sync::Arc;
use std::time::Duration;
static ARCHIVE_NAME: Lazy<String> =
@@ -50,13 +51,13 @@ trait UpdateCheckerEnvironment: Clone + Send + Sync {
#[derive(Clone)]
struct RealUpdateCheckerEnvironment {
- http_client: HttpClient,
+ http_client: Arc<HttpClient>,
cache_file_path: PathBuf,
current_time: chrono::DateTime<chrono::Utc>,
}
impl RealUpdateCheckerEnvironment {
- pub fn new(http_client: HttpClient, cache_file_path: PathBuf) -> Self {
+ pub fn new(http_client: Arc<HttpClient>, cache_file_path: PathBuf) -> Self {
Self {
http_client,
cache_file_path,
@@ -183,7 +184,10 @@ fn print_release_notes(current_version: &str, new_version: &str) {
}
}
-pub fn check_for_upgrades(http_client: HttpClient, cache_file_path: PathBuf) {
+pub fn check_for_upgrades(
+ http_client: Arc<HttpClient>,
+ cache_file_path: PathBuf,
+) {
if env::var("DENO_NO_UPDATE_CHECK").is_ok() {
return;
}
@@ -264,7 +268,7 @@ pub async fn upgrade(
upgrade_flags: UpgradeFlags,
) -> Result<(), AnyError> {
let factory = CliFactory::from_flags(flags).await?;
- let client = factory.http_client()?;
+ let client = factory.http_client();
let current_exe_path = std::env::current_exe()?;
let metadata = fs::metadata(&current_exe_path)?;
let permissions = metadata.permissions();
diff --git a/cli/worker.rs b/cli/worker.rs
index 64ce28477..ae8822fe4 100644
--- a/cli/worker.rs
+++ b/cli/worker.rs
@@ -21,7 +21,7 @@ use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_node;
use deno_runtime::deno_node::NodeResolution;
use deno_runtime::deno_node::NodeResolver;
-use deno_runtime::deno_tls::rustls::RootCertStore;
+use deno_runtime::deno_tls::RootCertStoreProvider;
use deno_runtime::deno_web::BlobStore;
use deno_runtime::fmt_errors::format_js_error;
use deno_runtime::inspector_server::InspectorServer;
@@ -96,7 +96,7 @@ struct SharedWorkerState {
shared_array_buffer_store: SharedArrayBufferStore,
compiled_wasm_module_store: CompiledWasmModuleStore,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
- root_cert_store: RootCertStore,
+ root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
node_fs: Arc<dyn deno_node::NodeFs>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
}
@@ -307,7 +307,7 @@ impl CliMainWorkerFactory {
has_node_specifier_checker: Box<dyn HasNodeSpecifierChecker>,
blob_store: BlobStore,
module_loader_factory: Box<dyn ModuleLoaderFactory>,
- root_cert_store: RootCertStore,
+ root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
node_fs: Arc<dyn deno_node::NodeFs>,
maybe_inspector_server: Option<Arc<InspectorServer>>,
options: CliMainWorkerOptions,
@@ -324,7 +324,7 @@ impl CliMainWorkerFactory {
shared_array_buffer_store: Default::default(),
compiled_wasm_module_store: Default::default(),
module_loader_factory,
- root_cert_store,
+ root_cert_store_provider,
node_fs,
maybe_inspector_server,
}),
@@ -434,7 +434,7 @@ impl CliMainWorkerFactory {
.options
.unsafely_ignore_certificate_errors
.clone(),
- root_cert_store: Some(shared.root_cert_store.clone()),
+ root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
seed: shared.options.seed,
source_map_getter: maybe_source_map_getter,
format_js_error_fn: Some(Arc::new(format_js_error)),
@@ -562,7 +562,7 @@ fn create_web_worker_callback(
.options
.unsafely_ignore_certificate_errors
.clone(),
- root_cert_store: Some(shared.root_cert_store.clone()),
+ root_cert_store_provider: Some(shared.root_cert_store_provider.clone()),
seed: shared.options.seed,
create_web_worker_cb,
preload_module_cb,
@@ -616,7 +616,7 @@ mod tests {
extensions: vec![],
startup_snapshot: Some(crate::js::deno_isolate_init()),
unsafely_ignore_certificate_errors: None,
- root_cert_store: None,
+ root_cert_store_provider: None,
seed: None,
format_js_error_fn: None,
source_map_getter: None,