mirror of
https://github.com/denoland/deno.git
synced 2025-01-12 00:54:02 -05:00
perf: lazily create RootCertStore (#18938)
This commit is contained in:
parent
ecc70eb58f
commit
913176313b
23 changed files with 344 additions and 173 deletions
|
@ -13,6 +13,7 @@ use self::package_json::PackageJsonDeps;
|
||||||
use ::import_map::ImportMap;
|
use ::import_map::ImportMap;
|
||||||
use deno_core::resolve_url_or_path;
|
use deno_core::resolve_url_or_path;
|
||||||
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot;
|
||||||
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ use deno_runtime::deno_tls::webpki_roots;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
use deno_runtime::permissions::PermissionsOptions;
|
use deno_runtime::permissions::PermissionsOptions;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use once_cell::sync::OnceCell;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
@ -61,6 +63,7 @@ use std::num::NonZeroUsize;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::cache::DenoDir;
|
use crate::cache::DenoDir;
|
||||||
use crate::file_fetcher::FileFetcher;
|
use crate::file_fetcher::FileFetcher;
|
||||||
|
@ -401,13 +404,62 @@ fn discover_package_json(
|
||||||
Ok(None)
|
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
|
/// Create and populate a root cert store based on the passed options and
|
||||||
/// environment.
|
/// environment.
|
||||||
pub fn get_root_cert_store(
|
pub fn get_root_cert_store(
|
||||||
maybe_root_path: Option<PathBuf>,
|
maybe_root_path: Option<PathBuf>,
|
||||||
maybe_ca_stores: Option<Vec<String>>,
|
maybe_ca_stores: Option<Vec<String>>,
|
||||||
maybe_ca_data: Option<CaData>,
|
maybe_ca_data: Option<CaData>,
|
||||||
) -> Result<RootCertStore, AnyError> {
|
) -> Result<RootCertStore, RootCertStoreLoadError> {
|
||||||
let mut root_cert_store = RootCertStore::empty();
|
let mut root_cert_store = RootCertStore::empty();
|
||||||
let ca_stores: Vec<String> = maybe_ca_stores
|
let ca_stores: Vec<String> = maybe_ca_stores
|
||||||
.or_else(|| {
|
.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 {
|
} else {
|
||||||
PathBuf::from(ca_file)
|
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);
|
let mut reader = BufReader::new(certfile);
|
||||||
rustls_pemfile::certs(&mut reader)
|
rustls_pemfile::certs(&mut reader)
|
||||||
}
|
}
|
||||||
|
@ -474,10 +528,7 @@ pub fn get_root_cert_store(
|
||||||
root_cert_store.add_parsable_certificates(&certs);
|
root_cert_store.add_parsable_certificates(&certs);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(anyhow!(
|
return Err(RootCertStoreLoadError::FailedAddPemFile(e.to_string()));
|
||||||
"Unable to add pem file to certificate store: {}",
|
|
||||||
e
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -799,12 +850,14 @@ impl CliOptions {
|
||||||
.map(|path| ModuleSpecifier::from_directory_path(path).unwrap())
|
.map(|path| ModuleSpecifier::from_directory_path(path).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_root_cert_store(&self) -> Result<RootCertStore, AnyError> {
|
pub fn resolve_root_cert_store_provider(
|
||||||
get_root_cert_store(
|
&self,
|
||||||
|
) -> Arc<dyn RootCertStoreProvider> {
|
||||||
|
Arc::new(CliRootCertStoreProvider::new(
|
||||||
None,
|
None,
|
||||||
self.flags.ca_stores.clone(),
|
self.flags.ca_stores.clone(),
|
||||||
self.flags.ca_data.clone(),
|
self.flags.ca_data.clone(),
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_ts_config_for_emit(
|
pub fn resolve_ts_config_for_emit(
|
||||||
|
|
|
@ -45,7 +45,7 @@ use deno_core::parking_lot::Mutex;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
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::deno_web::BlobStore;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
@ -129,14 +129,14 @@ struct CliFactoryServices {
|
||||||
dir: Deferred<DenoDir>,
|
dir: Deferred<DenoDir>,
|
||||||
caches: Deferred<Arc<Caches>>,
|
caches: Deferred<Arc<Caches>>,
|
||||||
file_fetcher: Deferred<Arc<FileFetcher>>,
|
file_fetcher: Deferred<Arc<FileFetcher>>,
|
||||||
http_client: Deferred<HttpClient>,
|
http_client: Deferred<Arc<HttpClient>>,
|
||||||
emit_cache: Deferred<EmitCache>,
|
emit_cache: Deferred<EmitCache>,
|
||||||
emitter: Deferred<Arc<Emitter>>,
|
emitter: Deferred<Arc<Emitter>>,
|
||||||
graph_container: Deferred<Arc<ModuleGraphContainer>>,
|
graph_container: Deferred<Arc<ModuleGraphContainer>>,
|
||||||
lockfile: Deferred<Option<Arc<Mutex<Lockfile>>>>,
|
lockfile: Deferred<Option<Arc<Mutex<Lockfile>>>>,
|
||||||
maybe_import_map: Deferred<Option<Arc<ImportMap>>>,
|
maybe_import_map: Deferred<Option<Arc<ImportMap>>>,
|
||||||
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
|
maybe_inspector_server: Deferred<Option<Arc<InspectorServer>>>,
|
||||||
root_cert_store: Deferred<RootCertStore>,
|
root_cert_store_provider: Deferred<Arc<dyn RootCertStoreProvider>>,
|
||||||
blob_store: Deferred<BlobStore>,
|
blob_store: Deferred<BlobStore>,
|
||||||
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
parsed_source_cache: Deferred<Arc<ParsedSourceCache>>,
|
||||||
resolver: Deferred<Arc<CliGraphResolver>>,
|
resolver: Deferred<Arc<CliGraphResolver>>,
|
||||||
|
@ -208,11 +208,11 @@ impl CliFactory {
|
||||||
self.services.blob_store.get_or_init(BlobStore::default)
|
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
|
self
|
||||||
.services
|
.services
|
||||||
.root_cert_store
|
.root_cert_store_provider
|
||||||
.get_or_try_init(|| self.options.resolve_root_cert_store())
|
.get_or_init(|| self.options.resolve_root_cert_store_provider())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn text_only_progress_bar(&self) -> &ProgressBar {
|
pub fn text_only_progress_bar(&self) -> &ProgressBar {
|
||||||
|
@ -222,12 +222,12 @@ impl CliFactory {
|
||||||
.get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly))
|
.get_or_init(|| ProgressBar::new(ProgressBarStyle::TextOnly))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn http_client(&self) -> Result<&HttpClient, AnyError> {
|
pub fn http_client(&self) -> &Arc<HttpClient> {
|
||||||
self.services.http_client.get_or_try_init(|| {
|
self.services.http_client.get_or_init(|| {
|
||||||
HttpClient::new(
|
Arc::new(HttpClient::new(
|
||||||
Some(self.root_cert_store()?.clone()),
|
Some(self.root_cert_store_provider().clone()),
|
||||||
self.options.unsafely_ignore_certificate_errors().clone(),
|
self.options.unsafely_ignore_certificate_errors().clone(),
|
||||||
)
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ impl CliFactory {
|
||||||
HttpCache::new(&self.deno_dir()?.deps_folder_path()),
|
HttpCache::new(&self.deno_dir()?.deps_folder_path()),
|
||||||
self.options.cache_setting(),
|
self.options.cache_setting(),
|
||||||
!self.options.no_remote(),
|
!self.options.no_remote(),
|
||||||
self.http_client()?.clone(),
|
self.http_client().clone(),
|
||||||
self.blob_store().clone(),
|
self.blob_store().clone(),
|
||||||
Some(self.text_only_progress_bar().clone()),
|
Some(self.text_only_progress_bar().clone()),
|
||||||
)))
|
)))
|
||||||
|
@ -256,7 +256,7 @@ impl CliFactory {
|
||||||
Ok(Arc::new(NpmCache::new(
|
Ok(Arc::new(NpmCache::new(
|
||||||
self.deno_dir()?.npm_folder_path(),
|
self.deno_dir()?.npm_folder_path(),
|
||||||
self.options.cache_setting(),
|
self.options.cache_setting(),
|
||||||
self.http_client()?.clone(),
|
self.http_client().clone(),
|
||||||
self.text_only_progress_bar().clone(),
|
self.text_only_progress_bar().clone(),
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
|
@ -267,7 +267,7 @@ impl CliFactory {
|
||||||
Ok(Arc::new(CliNpmRegistryApi::new(
|
Ok(Arc::new(CliNpmRegistryApi::new(
|
||||||
CliNpmRegistryApi::default_url().to_owned(),
|
CliNpmRegistryApi::default_url().to_owned(),
|
||||||
self.npm_cache()?.clone(),
|
self.npm_cache()?.clone(),
|
||||||
self.http_client()?.clone(),
|
self.http_client().clone(),
|
||||||
self.text_only_progress_bar().clone(),
|
self.text_only_progress_bar().clone(),
|
||||||
)))
|
)))
|
||||||
})
|
})
|
||||||
|
@ -554,7 +554,7 @@ impl CliFactory {
|
||||||
let options = self.cli_options().clone();
|
let options = self.cli_options().clone();
|
||||||
let main_worker_options = self.create_cli_main_worker_options()?;
|
let main_worker_options = self.create_cli_main_worker_options()?;
|
||||||
let node_fs = self.node_fs().clone();
|
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 node_resolver = self.node_resolver().await?.clone();
|
||||||
let npm_resolver = self.npm_resolver().await?.clone();
|
let npm_resolver = self.npm_resolver().await?.clone();
|
||||||
let maybe_inspector_server = self.maybe_inspector_server().clone();
|
let maybe_inspector_server = self.maybe_inspector_server().clone();
|
||||||
|
@ -578,7 +578,7 @@ impl CliFactory {
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
root_cert_store.clone(),
|
root_cert_store_provider.clone(),
|
||||||
node_fs.clone(),
|
node_fs.clone(),
|
||||||
maybe_inspector_server.clone(),
|
maybe_inspector_server.clone(),
|
||||||
main_worker_options.clone(),
|
main_worker_options.clone(),
|
||||||
|
@ -609,7 +609,7 @@ impl CliFactory {
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
self.root_cert_store()?.clone(),
|
self.root_cert_store_provider().clone(),
|
||||||
self.node_fs().clone(),
|
self.node_fs().clone(),
|
||||||
self.maybe_inspector_server().clone(),
|
self.maybe_inspector_server().clone(),
|
||||||
self.create_cli_main_worker_options()?,
|
self.create_cli_main_worker_options()?,
|
||||||
|
|
|
@ -178,7 +178,7 @@ pub struct FileFetcher {
|
||||||
cache: FileCache,
|
cache: FileCache,
|
||||||
cache_setting: CacheSetting,
|
cache_setting: CacheSetting,
|
||||||
pub http_cache: HttpCache,
|
pub http_cache: HttpCache,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
blob_store: BlobStore,
|
blob_store: BlobStore,
|
||||||
download_log_level: log::Level,
|
download_log_level: log::Level,
|
||||||
progress_bar: Option<ProgressBar>,
|
progress_bar: Option<ProgressBar>,
|
||||||
|
@ -189,7 +189,7 @@ impl FileFetcher {
|
||||||
http_cache: HttpCache,
|
http_cache: HttpCache,
|
||||||
cache_setting: CacheSetting,
|
cache_setting: CacheSetting,
|
||||||
allow_remote: bool,
|
allow_remote: bool,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
blob_store: BlobStore,
|
blob_store: BlobStore,
|
||||||
progress_bar: Option<ProgressBar>,
|
progress_bar: Option<ProgressBar>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -660,7 +660,7 @@ async fn fetch_once<'a>(
|
||||||
http_client: &HttpClient,
|
http_client: &HttpClient,
|
||||||
args: FetchOnceArgs<'a>,
|
args: FetchOnceArgs<'a>,
|
||||||
) -> Result<FetchOnceResult, AnyError> {
|
) -> 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 {
|
if let Some(etag) = args.maybe_etag {
|
||||||
let if_none_match_val = HeaderValue::from_str(&etag)?;
|
let if_none_match_val = HeaderValue::from_str(&etag)?;
|
||||||
|
@ -769,7 +769,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
cache_setting,
|
cache_setting,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
blob_store.clone(),
|
blob_store.clone(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1207,7 +1207,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::ReloadAll,
|
CacheSetting::ReloadAll,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1232,7 +1232,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Use,
|
CacheSetting::Use,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1257,7 +1257,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Use,
|
CacheSetting::Use,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1398,7 +1398,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Use,
|
CacheSetting::Use,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1426,7 +1426,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Use,
|
CacheSetting::Use,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1525,7 +1525,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Use,
|
CacheSetting::Use,
|
||||||
false,
|
false,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1550,7 +1550,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Only,
|
CacheSetting::Only,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -1558,7 +1558,7 @@ mod tests {
|
||||||
HttpCache::new(&location),
|
HttpCache::new(&location),
|
||||||
CacheSetting::Use,
|
CacheSetting::Use,
|
||||||
true,
|
true,
|
||||||
HttpClient::new(None, None).unwrap(),
|
Arc::new(HttpClient::new(None, None)),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
@ -2021,15 +2021,24 @@ mod tests {
|
||||||
#[ignore] // https://github.com/denoland/deno/issues/12561
|
#[ignore] // https://github.com/denoland/deno/issues/12561
|
||||||
async fn test_fetch_with_empty_certificate_store() {
|
async fn test_fetch_with_empty_certificate_store() {
|
||||||
use deno_runtime::deno_tls::rustls::RootCertStore;
|
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();
|
let _http_server_guard = test_util::http_server();
|
||||||
// Relies on external http server with a valid mozilla root CA cert.
|
// Relies on external http server with a valid mozilla root CA cert.
|
||||||
let url = Url::parse("https://deno.land").unwrap();
|
let url = Url::parse("https://deno.land").unwrap();
|
||||||
let client = HttpClient::new(
|
let client = HttpClient::new(
|
||||||
Some(RootCertStore::empty()), // no certs loaded at all
|
// no certs loaded at all
|
||||||
|
Some(Arc::new(ValueRootCertStoreProvider(RootCertStore::empty()))),
|
||||||
None,
|
None,
|
||||||
)
|
);
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let result = fetch_once(
|
let result = fetch_once(
|
||||||
&client,
|
&client,
|
||||||
|
|
|
@ -15,8 +15,9 @@ use deno_runtime::deno_fetch::create_http_client;
|
||||||
use deno_runtime::deno_fetch::reqwest;
|
use deno_runtime::deno_fetch::reqwest;
|
||||||
use deno_runtime::deno_fetch::reqwest::header::LOCATION;
|
use deno_runtime::deno_fetch::reqwest::header::LOCATION;
|
||||||
use deno_runtime::deno_fetch::reqwest::Response;
|
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::collections::HashMap;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
@ -217,34 +218,68 @@ impl CacheSemantics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
pub struct HttpClient {
|
||||||
pub struct HttpClient(reqwest::Client);
|
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 {
|
impl HttpClient {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
root_cert_store: Option<RootCertStore>,
|
root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
||||||
) -> Result<Self, AnyError> {
|
) -> Self {
|
||||||
Ok(HttpClient::from_client(create_http_client(
|
Self {
|
||||||
get_user_agent(),
|
root_cert_store_provider,
|
||||||
root_cert_store,
|
|
||||||
vec![],
|
|
||||||
None,
|
|
||||||
unsafely_ignore_certificate_errors,
|
unsafely_ignore_certificate_errors,
|
||||||
None,
|
cell: Default::default(),
|
||||||
)?))
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
pub fn from_client(client: reqwest::Client) -> Self {
|
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.
|
/// Do a GET request without following redirects.
|
||||||
pub fn get_no_redirect<U: reqwest::IntoUrl>(
|
pub fn get_no_redirect<U: reqwest::IntoUrl>(
|
||||||
&self,
|
&self,
|
||||||
url: U,
|
url: U,
|
||||||
) -> reqwest::RequestBuilder {
|
) -> Result<reqwest::RequestBuilder, AnyError> {
|
||||||
self.0.get(url)
|
Ok(self.client()?.get(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn download_text<U: reqwest::IntoUrl>(
|
pub async fn download_text<U: reqwest::IntoUrl>(
|
||||||
|
@ -306,12 +341,13 @@ impl HttpClient {
|
||||||
url: U,
|
url: U,
|
||||||
) -> Result<Response, AnyError> {
|
) -> Result<Response, AnyError> {
|
||||||
let mut url = url.into_url()?;
|
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();
|
let status = response.status();
|
||||||
if status.is_redirection() {
|
if status.is_redirection() {
|
||||||
for _ in 0..5 {
|
for _ in 0..5 {
|
||||||
let new_url = resolve_redirect_from_response(&url, &response)?;
|
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();
|
let status = new_response.status();
|
||||||
if status.is_redirection() {
|
if status.is_redirection() {
|
||||||
response = new_response;
|
response = new_response;
|
||||||
|
@ -357,7 +393,7 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_http_client_download_redirect() {
|
async fn test_http_client_download_redirect() {
|
||||||
let _http_server_guard = test_util::http_server();
|
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
|
// make a request to the redirect server
|
||||||
let text = client
|
let text = client
|
||||||
|
|
|
@ -12,6 +12,8 @@ use deno_core::ModuleSpecifier;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_node::PackageJson;
|
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 deno_runtime::deno_web::BlobStore;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
use log::error;
|
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::ProgressBar;
|
||||||
use crate::util::progress_bar::ProgressBarStyle;
|
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)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
|
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
|
/// The collection of documents that the server is currently handling, either
|
||||||
/// on disk or "open" within the client.
|
/// on disk or "open" within the client.
|
||||||
pub documents: Documents,
|
pub documents: Documents,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
/// Handles module registries, which allow discovery of modules
|
/// Handles module registries, which allow discovery of modules
|
||||||
module_registries: ModuleRegistry,
|
module_registries: ModuleRegistry,
|
||||||
/// The path to the module registries cache
|
/// The path to the module registries cache
|
||||||
|
@ -420,7 +430,7 @@ impl LanguageServer {
|
||||||
|
|
||||||
fn create_lsp_structs(
|
fn create_lsp_structs(
|
||||||
dir: &DenoDir,
|
dir: &DenoDir,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
) -> (
|
) -> (
|
||||||
Arc<CliNpmRegistryApi>,
|
Arc<CliNpmRegistryApi>,
|
||||||
Arc<NpmCache>,
|
Arc<NpmCache>,
|
||||||
|
@ -469,10 +479,9 @@ impl Inner {
|
||||||
let dir =
|
let dir =
|
||||||
DenoDir::new(maybe_custom_root).expect("could not access DENO_DIR");
|
DenoDir::new(maybe_custom_root).expect("could not access DENO_DIR");
|
||||||
let module_registries_location = dir.registries_folder_path();
|
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 =
|
let module_registries =
|
||||||
ModuleRegistry::new(&module_registries_location, http_client.clone())
|
ModuleRegistry::new(&module_registries_location, http_client.clone());
|
||||||
.unwrap();
|
|
||||||
let location = dir.deps_folder_path();
|
let location = dir.deps_folder_path();
|
||||||
let documents = Documents::new(&location, client.kind());
|
let documents = Documents::new(&location, client.kind());
|
||||||
let deps_http_cache = HttpCache::new(&location);
|
let deps_http_cache = HttpCache::new(&location);
|
||||||
|
@ -775,20 +784,22 @@ impl Inner {
|
||||||
.root_uri
|
.root_uri
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|uri| specifier_to_file_path(uri).ok());
|
.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,
|
maybe_root_path,
|
||||||
workspace_settings.certificate_stores,
|
workspace_settings.certificate_stores,
|
||||||
workspace_settings.tls_certificate.map(CaData::File),
|
workspace_settings.tls_certificate.map(CaData::File),
|
||||||
)?);
|
|
||||||
let module_registries_location = dir.registries_folder_path();
|
|
||||||
self.http_client = HttpClient::new(
|
|
||||||
root_cert_store,
|
|
||||||
workspace_settings.unsafely_ignore_certificate_errors,
|
|
||||||
)?;
|
)?;
|
||||||
|
let root_cert_store_provider =
|
||||||
|
Arc::new(LspRootCertStoreProvider(root_cert_store));
|
||||||
|
let module_registries_location = dir.registries_folder_path();
|
||||||
|
self.http_client = Arc::new(HttpClient::new(
|
||||||
|
Some(root_cert_store_provider),
|
||||||
|
workspace_settings.unsafely_ignore_certificate_errors,
|
||||||
|
));
|
||||||
self.module_registries = ModuleRegistry::new(
|
self.module_registries = ModuleRegistry::new(
|
||||||
&module_registries_location,
|
&module_registries_location,
|
||||||
self.http_client.clone(),
|
self.http_client.clone(),
|
||||||
)?;
|
);
|
||||||
self.module_registries_location = module_registries_location;
|
self.module_registries_location = module_registries_location;
|
||||||
(
|
(
|
||||||
self.npm_api,
|
self.npm_api,
|
||||||
|
|
|
@ -35,6 +35,7 @@ use log::error;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::Arc;
|
||||||
use tower_lsp::lsp_types as lsp;
|
use tower_lsp::lsp_types as lsp;
|
||||||
|
|
||||||
const CONFIG_PATH: &str = "/.well-known/deno-import-intellisense.json";
|
const CONFIG_PATH: &str = "/.well-known/deno-import-intellisense.json";
|
||||||
|
@ -425,16 +426,13 @@ impl Default for ModuleRegistry {
|
||||||
// custom root.
|
// custom root.
|
||||||
let dir = DenoDir::new(None).unwrap();
|
let dir = DenoDir::new(None).unwrap();
|
||||||
let location = dir.registries_folder_path();
|
let location = dir.registries_folder_path();
|
||||||
let http_client = HttpClient::new(None, None).unwrap();
|
let http_client = Arc::new(HttpClient::new(None, None));
|
||||||
Self::new(&location, http_client).unwrap()
|
Self::new(&location, http_client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModuleRegistry {
|
impl ModuleRegistry {
|
||||||
pub fn new(
|
pub fn new(location: &Path, http_client: Arc<HttpClient>) -> Self {
|
||||||
location: &Path,
|
|
||||||
http_client: HttpClient,
|
|
||||||
) -> Result<Self, AnyError> {
|
|
||||||
let http_cache = HttpCache::new(location);
|
let http_cache = HttpCache::new(location);
|
||||||
let mut file_fetcher = FileFetcher::new(
|
let mut file_fetcher = FileFetcher::new(
|
||||||
http_cache,
|
http_cache,
|
||||||
|
@ -446,10 +444,10 @@ impl ModuleRegistry {
|
||||||
);
|
);
|
||||||
file_fetcher.set_download_log_level(super::logging::lsp_log_level());
|
file_fetcher.set_download_log_level(super::logging::lsp_log_level());
|
||||||
|
|
||||||
Ok(Self {
|
Self {
|
||||||
origins: HashMap::new(),
|
origins: HashMap::new(),
|
||||||
file_fetcher,
|
file_fetcher,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn complete_literal(
|
fn complete_literal(
|
||||||
|
@ -1251,8 +1249,7 @@ mod tests {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let location = temp_dir.path().join("registries");
|
let location = temp_dir.path().join("registries");
|
||||||
let mut module_registry =
|
let mut module_registry =
|
||||||
ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
|
ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
|
||||||
.unwrap();
|
|
||||||
module_registry
|
module_registry
|
||||||
.enable("http://localhost:4545/")
|
.enable("http://localhost:4545/")
|
||||||
.await
|
.await
|
||||||
|
@ -1313,8 +1310,7 @@ mod tests {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let location = temp_dir.path().join("registries");
|
let location = temp_dir.path().join("registries");
|
||||||
let mut module_registry =
|
let mut module_registry =
|
||||||
ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
|
ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
|
||||||
.unwrap();
|
|
||||||
module_registry
|
module_registry
|
||||||
.enable("http://localhost:4545/")
|
.enable("http://localhost:4545/")
|
||||||
.await
|
.await
|
||||||
|
@ -1537,8 +1533,7 @@ mod tests {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let location = temp_dir.path().join("registries");
|
let location = temp_dir.path().join("registries");
|
||||||
let mut module_registry =
|
let mut module_registry =
|
||||||
ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
|
ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
|
||||||
.unwrap();
|
|
||||||
module_registry
|
module_registry
|
||||||
.enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-key-first.json")
|
.enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-key-first.json")
|
||||||
.await
|
.await
|
||||||
|
@ -1608,8 +1603,7 @@ mod tests {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let location = temp_dir.path().join("registries");
|
let location = temp_dir.path().join("registries");
|
||||||
let mut module_registry =
|
let mut module_registry =
|
||||||
ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
|
ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
|
||||||
.unwrap();
|
|
||||||
module_registry
|
module_registry
|
||||||
.enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-complex.json")
|
.enable_custom("http://localhost:4545/lsp/registries/deno-import-intellisense-complex.json")
|
||||||
.await
|
.await
|
||||||
|
@ -1660,8 +1654,7 @@ mod tests {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let location = temp_dir.path().join("registries");
|
let location = temp_dir.path().join("registries");
|
||||||
let module_registry =
|
let module_registry =
|
||||||
ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
|
ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
|
||||||
.unwrap();
|
|
||||||
let result = module_registry.check_origin("http://localhost:4545").await;
|
let result = module_registry.check_origin("http://localhost:4545").await;
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
}
|
}
|
||||||
|
@ -1672,8 +1665,7 @@ mod tests {
|
||||||
let temp_dir = TempDir::new();
|
let temp_dir = TempDir::new();
|
||||||
let location = temp_dir.path().join("registries");
|
let location = temp_dir.path().join("registries");
|
||||||
let module_registry =
|
let module_registry =
|
||||||
ModuleRegistry::new(&location, HttpClient::new(None, None).unwrap())
|
ModuleRegistry::new(&location, Arc::new(HttpClient::new(None, None)));
|
||||||
.unwrap();
|
|
||||||
let result = module_registry.check_origin("https://example.com").await;
|
let result = module_registry.check_origin("https://example.com").await;
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let err = result.unwrap_err().to_string();
|
let err = result.unwrap_err().to_string();
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::collections::HashSet;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_ast::ModuleSpecifier;
|
use deno_ast::ModuleSpecifier;
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
|
@ -295,7 +296,7 @@ impl ReadonlyNpmCache {
|
||||||
pub struct NpmCache {
|
pub struct NpmCache {
|
||||||
readonly: ReadonlyNpmCache,
|
readonly: ReadonlyNpmCache,
|
||||||
cache_setting: CacheSetting,
|
cache_setting: CacheSetting,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
/// ensures a package is only downloaded once per run
|
/// ensures a package is only downloaded once per run
|
||||||
previously_reloaded_packages: Mutex<HashSet<NpmPackageNv>>,
|
previously_reloaded_packages: Mutex<HashSet<NpmPackageNv>>,
|
||||||
|
@ -305,7 +306,7 @@ impl NpmCache {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
cache_dir_path: PathBuf,
|
cache_dir_path: PathBuf,
|
||||||
cache_setting: CacheSetting,
|
cache_setting: CacheSetting,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
@ -63,7 +63,7 @@ impl CliNpmRegistryApi {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
base_url: Url,
|
base_url: Url,
|
||||||
cache: Arc<NpmCache>,
|
cache: Arc<NpmCache>,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self(Some(Arc::new(CliNpmRegistryApiInner {
|
Self(Some(Arc::new(CliNpmRegistryApiInner {
|
||||||
|
@ -172,7 +172,7 @@ struct CliNpmRegistryApiInner {
|
||||||
force_reload_flag: AtomicFlag,
|
force_reload_flag: AtomicFlag,
|
||||||
mem_cache: Mutex<HashMap<String, CacheItem>>,
|
mem_cache: Mutex<HashMap<String, CacheItem>>,
|
||||||
previously_reloaded_packages: Mutex<HashSet<String>>,
|
previously_reloaded_packages: Mutex<HashSet<String>>,
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
progress_bar: ProgressBar,
|
progress_bar: ProgressBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ use deno_core::ResolutionKind;
|
||||||
use deno_graph::source::Resolver;
|
use deno_graph::source::Resolver;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
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::deno_web::BlobStore;
|
||||||
use deno_runtime::permissions::Permissions;
|
use deno_runtime::permissions::Permissions;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
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(
|
pub async fn run(
|
||||||
eszip: eszip::EszipV2,
|
eszip: eszip::EszipV2,
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let main_module = &metadata.entrypoint;
|
let main_module = &metadata.entrypoint;
|
||||||
let dir = DenoDir::new(None)?;
|
let dir = DenoDir::new(None)?;
|
||||||
let root_cert_store = get_root_cert_store(
|
let root_cert_store_provider = Arc::new(StandaloneRootCertStoreProvider {
|
||||||
None,
|
ca_stores: metadata.ca_stores,
|
||||||
metadata.ca_stores,
|
ca_data: metadata.ca_data.map(CaData::Bytes),
|
||||||
metadata.ca_data.map(CaData::Bytes),
|
cell: Default::default(),
|
||||||
)?;
|
});
|
||||||
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
|
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
|
||||||
let http_client = HttpClient::new(
|
let http_client = Arc::new(HttpClient::new(
|
||||||
Some(root_cert_store.clone()),
|
Some(root_cert_store_provider.clone()),
|
||||||
metadata.unsafely_ignore_certificate_errors.clone(),
|
metadata.unsafely_ignore_certificate_errors.clone(),
|
||||||
)?;
|
));
|
||||||
let npm_registry_url = CliNpmRegistryApi::default_url().to_owned();
|
let npm_registry_url = CliNpmRegistryApi::default_url().to_owned();
|
||||||
let npm_cache = Arc::new(NpmCache::new(
|
let npm_cache = Arc::new(NpmCache::new(
|
||||||
dir.npm_folder_path(),
|
dir.npm_folder_path(),
|
||||||
|
@ -235,7 +252,7 @@ pub async fn run(
|
||||||
Box::new(StandaloneHasNodeSpecifierChecker),
|
Box::new(StandaloneHasNodeSpecifierChecker),
|
||||||
BlobStore::default(),
|
BlobStore::default(),
|
||||||
Box::new(module_loader_factory),
|
Box::new(module_loader_factory),
|
||||||
root_cert_store,
|
root_cert_store_provider,
|
||||||
node_fs,
|
node_fs,
|
||||||
None,
|
None,
|
||||||
CliMainWorkerOptions {
|
CliMainWorkerOptions {
|
||||||
|
|
|
@ -133,7 +133,7 @@ pub async fn infer_name_from_url(url: &Url) -> Option<String> {
|
||||||
let mut url = url.clone();
|
let mut url = url.clone();
|
||||||
|
|
||||||
if url.path() == "/" {
|
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 {
|
if let Ok(res) = client.get_redirected_response(url.clone()).await {
|
||||||
url = res.url().clone();
|
url = res.url().clone();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// map specified and bare specifier is used on the command line
|
||||||
let factory = CliFactory::from_flags(flags).await?;
|
let factory = CliFactory::from_flags(flags).await?;
|
||||||
let deno_dir = factory.deno_dir()?;
|
let deno_dir = factory.deno_dir()?;
|
||||||
let http_client = factory.http_client()?;
|
let http_client = factory.http_client();
|
||||||
let cli_options = factory.cli_options();
|
let cli_options = factory.cli_options();
|
||||||
|
|
||||||
// Run a background task that checks for available upgrades. If an earlier
|
// Run a background task that checks for available upgrades. If an earlier
|
||||||
|
|
|
@ -26,7 +26,7 @@ pub async fn compile(
|
||||||
let factory = CliFactory::from_flags(flags).await?;
|
let factory = CliFactory::from_flags(flags).await?;
|
||||||
let cli_options = factory.cli_options();
|
let cli_options = factory.cli_options();
|
||||||
let file_fetcher = factory.file_fetcher()?;
|
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 deno_dir = factory.deno_dir()?;
|
||||||
let module_graph_builder = factory.module_graph_builder().await?;
|
let module_graph_builder = factory.module_graph_builder().await?;
|
||||||
let parsed_source_cache = factory.parsed_source_cache()?;
|
let parsed_source_cache = factory.parsed_source_cache()?;
|
||||||
|
|
|
@ -26,6 +26,7 @@ use std::ops::Sub;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
static ARCHIVE_NAME: Lazy<String> =
|
static ARCHIVE_NAME: Lazy<String> =
|
||||||
|
@ -50,13 +51,13 @@ trait UpdateCheckerEnvironment: Clone + Send + Sync {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct RealUpdateCheckerEnvironment {
|
struct RealUpdateCheckerEnvironment {
|
||||||
http_client: HttpClient,
|
http_client: Arc<HttpClient>,
|
||||||
cache_file_path: PathBuf,
|
cache_file_path: PathBuf,
|
||||||
current_time: chrono::DateTime<chrono::Utc>,
|
current_time: chrono::DateTime<chrono::Utc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RealUpdateCheckerEnvironment {
|
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 {
|
Self {
|
||||||
http_client,
|
http_client,
|
||||||
cache_file_path,
|
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() {
|
if env::var("DENO_NO_UPDATE_CHECK").is_ok() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +268,7 @@ pub async fn upgrade(
|
||||||
upgrade_flags: UpgradeFlags,
|
upgrade_flags: UpgradeFlags,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let factory = CliFactory::from_flags(flags).await?;
|
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 current_exe_path = std::env::current_exe()?;
|
||||||
let metadata = fs::metadata(¤t_exe_path)?;
|
let metadata = fs::metadata(¤t_exe_path)?;
|
||||||
let permissions = metadata.permissions();
|
let permissions = metadata.permissions();
|
||||||
|
|
|
@ -21,7 +21,7 @@ use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
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::deno_web::BlobStore;
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
|
@ -96,7 +96,7 @@ struct SharedWorkerState {
|
||||||
shared_array_buffer_store: SharedArrayBufferStore,
|
shared_array_buffer_store: SharedArrayBufferStore,
|
||||||
compiled_wasm_module_store: CompiledWasmModuleStore,
|
compiled_wasm_module_store: CompiledWasmModuleStore,
|
||||||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||||
root_cert_store: RootCertStore,
|
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||||
node_fs: Arc<dyn deno_node::NodeFs>,
|
node_fs: Arc<dyn deno_node::NodeFs>,
|
||||||
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ impl CliMainWorkerFactory {
|
||||||
has_node_specifier_checker: Box<dyn HasNodeSpecifierChecker>,
|
has_node_specifier_checker: Box<dyn HasNodeSpecifierChecker>,
|
||||||
blob_store: BlobStore,
|
blob_store: BlobStore,
|
||||||
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
module_loader_factory: Box<dyn ModuleLoaderFactory>,
|
||||||
root_cert_store: RootCertStore,
|
root_cert_store_provider: Arc<dyn RootCertStoreProvider>,
|
||||||
node_fs: Arc<dyn deno_node::NodeFs>,
|
node_fs: Arc<dyn deno_node::NodeFs>,
|
||||||
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
maybe_inspector_server: Option<Arc<InspectorServer>>,
|
||||||
options: CliMainWorkerOptions,
|
options: CliMainWorkerOptions,
|
||||||
|
@ -324,7 +324,7 @@ impl CliMainWorkerFactory {
|
||||||
shared_array_buffer_store: Default::default(),
|
shared_array_buffer_store: Default::default(),
|
||||||
compiled_wasm_module_store: Default::default(),
|
compiled_wasm_module_store: Default::default(),
|
||||||
module_loader_factory,
|
module_loader_factory,
|
||||||
root_cert_store,
|
root_cert_store_provider,
|
||||||
node_fs,
|
node_fs,
|
||||||
maybe_inspector_server,
|
maybe_inspector_server,
|
||||||
}),
|
}),
|
||||||
|
@ -434,7 +434,7 @@ impl CliMainWorkerFactory {
|
||||||
.options
|
.options
|
||||||
.unsafely_ignore_certificate_errors
|
.unsafely_ignore_certificate_errors
|
||||||
.clone(),
|
.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,
|
seed: shared.options.seed,
|
||||||
source_map_getter: maybe_source_map_getter,
|
source_map_getter: maybe_source_map_getter,
|
||||||
format_js_error_fn: Some(Arc::new(format_js_error)),
|
format_js_error_fn: Some(Arc::new(format_js_error)),
|
||||||
|
@ -562,7 +562,7 @@ fn create_web_worker_callback(
|
||||||
.options
|
.options
|
||||||
.unsafely_ignore_certificate_errors
|
.unsafely_ignore_certificate_errors
|
||||||
.clone(),
|
.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,
|
seed: shared.options.seed,
|
||||||
create_web_worker_cb,
|
create_web_worker_cb,
|
||||||
preload_module_cb,
|
preload_module_cb,
|
||||||
|
@ -616,7 +616,7 @@ mod tests {
|
||||||
extensions: vec![],
|
extensions: vec![],
|
||||||
startup_snapshot: Some(crate::js::deno_isolate_init()),
|
startup_snapshot: Some(crate::js::deno_isolate_init()),
|
||||||
unsafely_ignore_certificate_errors: None,
|
unsafely_ignore_certificate_errors: None,
|
||||||
root_cert_store: None,
|
root_cert_store_provider: None,
|
||||||
seed: None,
|
seed: None,
|
||||||
format_js_error_fn: None,
|
format_js_error_fn: None,
|
||||||
source_map_getter: None,
|
source_map_getter: None,
|
||||||
|
|
|
@ -3,7 +3,16 @@
|
||||||
mod byte_stream;
|
mod byte_stream;
|
||||||
mod fs_fetch_handler;
|
mod fs_fetch_handler;
|
||||||
|
|
||||||
use data_url::DataUrl;
|
use std::borrow::Cow;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::cmp::min;
|
||||||
|
use std::convert::From;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::futures::stream::Peekable;
|
use deno_core::futures::stream::Peekable;
|
||||||
|
@ -29,6 +38,9 @@ use deno_core::ResourceId;
|
||||||
use deno_core::ZeroCopyBuf;
|
use deno_core::ZeroCopyBuf;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
use deno_tls::Proxy;
|
use deno_tls::Proxy;
|
||||||
|
use deno_tls::RootCertStoreProvider;
|
||||||
|
|
||||||
|
use data_url::DataUrl;
|
||||||
use http::header::CONTENT_LENGTH;
|
use http::header::CONTENT_LENGTH;
|
||||||
use http::Uri;
|
use http::Uri;
|
||||||
use reqwest::header::HeaderMap;
|
use reqwest::header::HeaderMap;
|
||||||
|
@ -46,14 +58,6 @@ use reqwest::RequestBuilder;
|
||||||
use reqwest::Response;
|
use reqwest::Response;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use std::borrow::Cow;
|
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::cmp::min;
|
|
||||||
use std::convert::From;
|
|
||||||
use std::path::Path;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::rc::Rc;
|
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
// Re-export reqwest and data_url
|
// Re-export reqwest and data_url
|
||||||
|
@ -67,7 +71,7 @@ use crate::byte_stream::MpscByteStream;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Options {
|
pub struct Options {
|
||||||
pub user_agent: String,
|
pub user_agent: String,
|
||||||
pub root_cert_store: Option<RootCertStore>,
|
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
pub proxy: Option<Proxy>,
|
pub proxy: Option<Proxy>,
|
||||||
pub request_builder_hook:
|
pub request_builder_hook:
|
||||||
Option<fn(RequestBuilder) -> Result<RequestBuilder, AnyError>>,
|
Option<fn(RequestBuilder) -> Result<RequestBuilder, AnyError>>,
|
||||||
|
@ -76,11 +80,20 @@ pub struct Options {
|
||||||
pub file_fetch_handler: Rc<dyn FetchHandler>,
|
pub file_fetch_handler: Rc<dyn FetchHandler>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Options {
|
||||||
|
pub fn root_cert_store(&self) -> Result<Option<RootCertStore>, AnyError> {
|
||||||
|
Ok(match &self.root_cert_store_provider {
|
||||||
|
Some(provider) => Some(provider.get_or_try_init()?.clone()),
|
||||||
|
None => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Options {
|
impl Default for Options {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
user_agent: "".to_string(),
|
user_agent: "".to_string(),
|
||||||
root_cert_store: None,
|
root_cert_store_provider: None,
|
||||||
proxy: None,
|
proxy: None,
|
||||||
request_builder_hook: None,
|
request_builder_hook: None,
|
||||||
unsafely_ignore_certificate_errors: None,
|
unsafely_ignore_certificate_errors: None,
|
||||||
|
@ -111,18 +124,7 @@ deno_core::extension!(deno_fetch,
|
||||||
options: Options,
|
options: Options,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
state.put::<Options>(options.options.clone());
|
state.put::<Options>(options.options);
|
||||||
state.put::<reqwest::Client>({
|
|
||||||
create_http_client(
|
|
||||||
&options.options.user_agent,
|
|
||||||
options.options.root_cert_store,
|
|
||||||
vec![],
|
|
||||||
options.options.proxy,
|
|
||||||
options.options.unsafely_ignore_certificate_errors,
|
|
||||||
options.options.client_cert_chain_and_key
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -189,6 +191,26 @@ pub struct FetchReturn {
|
||||||
cancel_handle_rid: Option<ResourceId>,
|
cancel_handle_rid: Option<ResourceId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_or_create_client_from_state(
|
||||||
|
state: &mut OpState,
|
||||||
|
) -> Result<reqwest::Client, AnyError> {
|
||||||
|
if let Some(client) = state.try_borrow::<reqwest::Client>() {
|
||||||
|
Ok(client.clone())
|
||||||
|
} else {
|
||||||
|
let options = state.borrow::<Options>();
|
||||||
|
let client = create_http_client(
|
||||||
|
&options.user_agent,
|
||||||
|
options.root_cert_store()?,
|
||||||
|
vec![],
|
||||||
|
options.proxy.clone(),
|
||||||
|
options.unsafely_ignore_certificate_errors.clone(),
|
||||||
|
options.client_cert_chain_and_key.clone(),
|
||||||
|
)?;
|
||||||
|
state.put::<reqwest::Client>(client.clone());
|
||||||
|
Ok(client)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
pub fn op_fetch<FP>(
|
pub fn op_fetch<FP>(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
|
@ -207,8 +229,7 @@ where
|
||||||
let r = state.resource_table.get::<HttpClientResource>(rid)?;
|
let r = state.resource_table.get::<HttpClientResource>(rid)?;
|
||||||
r.client.clone()
|
r.client.clone()
|
||||||
} else {
|
} else {
|
||||||
let client = state.borrow::<reqwest::Client>();
|
get_or_create_client_from_state(state)?
|
||||||
client.clone()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let method = Method::from_bytes(&method)?;
|
let method = Method::from_bytes(&method)?;
|
||||||
|
@ -632,7 +653,7 @@ where
|
||||||
|
|
||||||
let client = create_http_client(
|
let client = create_http_client(
|
||||||
&options.user_agent,
|
&options.user_agent,
|
||||||
options.root_cert_store.clone(),
|
options.root_cert_store()?,
|
||||||
ca_certs,
|
ca_certs,
|
||||||
args.proxy,
|
args.proxy,
|
||||||
options.unsafely_ignore_certificate_errors.clone(),
|
options.unsafely_ignore_certificate_errors.clone(),
|
||||||
|
|
|
@ -11,10 +11,12 @@ pub mod resolve_addr;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::rustls::RootCertStore;
|
||||||
|
use deno_tls::RootCertStoreProvider;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub trait NetPermissions {
|
pub trait NetPermissions {
|
||||||
fn check_net<T: AsRef<str>>(
|
fn check_net<T: AsRef<str>>(
|
||||||
|
@ -67,7 +69,16 @@ pub fn get_declaration() -> PathBuf {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct DefaultTlsOptions {
|
pub struct DefaultTlsOptions {
|
||||||
pub root_cert_store: Option<RootCertStore>,
|
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DefaultTlsOptions {
|
||||||
|
pub fn root_cert_store(&self) -> Result<Option<RootCertStore>, AnyError> {
|
||||||
|
Ok(match &self.root_cert_store_provider {
|
||||||
|
Some(provider) => Some(provider.get_or_try_init()?.clone()),
|
||||||
|
None => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `UnsafelyIgnoreCertificateErrors` is a wrapper struct so it can be placed inside `GothamState`;
|
/// `UnsafelyIgnoreCertificateErrors` is a wrapper struct so it can be placed inside `GothamState`;
|
||||||
|
@ -113,13 +124,13 @@ deno_core::extension!(deno_net,
|
||||||
],
|
],
|
||||||
esm = [ "01_net.js", "02_tls.js" ],
|
esm = [ "01_net.js", "02_tls.js" ],
|
||||||
options = {
|
options = {
|
||||||
root_cert_store: Option<RootCertStore>,
|
root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
unstable: bool,
|
unstable: bool,
|
||||||
unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
state.put(DefaultTlsOptions {
|
state.put(DefaultTlsOptions {
|
||||||
root_cert_store: options.root_cert_store,
|
root_cert_store_provider: options.root_cert_store_provider,
|
||||||
});
|
});
|
||||||
state.put(UnstableChecker { unstable: options.unstable });
|
state.put(UnstableChecker { unstable: options.unstable });
|
||||||
state.put(UnsafelyIgnoreCertificateErrors(
|
state.put(UnsafelyIgnoreCertificateErrors(
|
||||||
|
|
|
@ -813,14 +813,10 @@ where
|
||||||
.try_borrow::<UnsafelyIgnoreCertificateErrors>()
|
.try_borrow::<UnsafelyIgnoreCertificateErrors>()
|
||||||
.and_then(|it| it.0.clone());
|
.and_then(|it| it.0.clone());
|
||||||
|
|
||||||
// TODO(@justinmchase): Ideally the certificate store is created once
|
|
||||||
// and not cloned. The store should be wrapped in Arc<T> to reduce
|
|
||||||
// copying memory unnecessarily.
|
|
||||||
let root_cert_store = state
|
let root_cert_store = state
|
||||||
.borrow()
|
.borrow()
|
||||||
.borrow::<DefaultTlsOptions>()
|
.borrow::<DefaultTlsOptions>()
|
||||||
.root_cert_store
|
.root_cert_store()?;
|
||||||
.clone();
|
|
||||||
|
|
||||||
let resource_rc = state
|
let resource_rc = state
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -912,8 +908,7 @@ where
|
||||||
let root_cert_store = state
|
let root_cert_store = state
|
||||||
.borrow()
|
.borrow()
|
||||||
.borrow::<DefaultTlsOptions>()
|
.borrow::<DefaultTlsOptions>()
|
||||||
.root_cert_store
|
.root_cert_store()?;
|
||||||
.clone();
|
|
||||||
let hostname_dns = ServerName::try_from(&*addr.hostname)
|
let hostname_dns = ServerName::try_from(&*addr.hostname)
|
||||||
.map_err(|_| invalid_hostname(&addr.hostname))?;
|
.map_err(|_| invalid_hostname(&addr.hostname))?;
|
||||||
let connect_addr = resolve_addr(&addr.hostname, addr.port)
|
let connect_addr = resolve_addr(&addr.hostname, addr.port)
|
||||||
|
|
|
@ -34,6 +34,14 @@ use std::io::Cursor;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
/// Lazily resolves the root cert store.
|
||||||
|
///
|
||||||
|
/// This was done because the root cert store is not needed in all cases
|
||||||
|
/// and takes a bit of time to initialize.
|
||||||
|
pub trait RootCertStoreProvider: Send + Sync {
|
||||||
|
fn get_or_try_init(&self) -> Result<&RootCertStore, AnyError>;
|
||||||
|
}
|
||||||
|
|
||||||
// This extension has no runtime apis, it only exports some shared native functions.
|
// This extension has no runtime apis, it only exports some shared native functions.
|
||||||
deno_core::extension!(deno_tls);
|
deno_core::extension!(deno_tls);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ use deno_core::ZeroCopyBuf;
|
||||||
use deno_net::raw::take_network_stream_resource;
|
use deno_net::raw::take_network_stream_resource;
|
||||||
use deno_net::raw::NetworkStream;
|
use deno_net::raw::NetworkStream;
|
||||||
use deno_tls::create_client_config;
|
use deno_tls::create_client_config;
|
||||||
|
use deno_tls::RootCertStoreProvider;
|
||||||
use http::header::CONNECTION;
|
use http::header::CONNECTION;
|
||||||
use http::header::UPGRADE;
|
use http::header::UPGRADE;
|
||||||
use http::HeaderName;
|
use http::HeaderName;
|
||||||
|
@ -54,7 +55,17 @@ use fastwebsockets::WebSocket;
|
||||||
mod stream;
|
mod stream;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WsRootStore(pub Option<RootCertStore>);
|
pub struct WsRootStoreProvider(Option<Arc<dyn RootCertStoreProvider>>);
|
||||||
|
|
||||||
|
impl WsRootStoreProvider {
|
||||||
|
pub fn get_or_try_init(&self) -> Result<Option<RootCertStore>, AnyError> {
|
||||||
|
Ok(match &self.0 {
|
||||||
|
Some(provider) => Some(provider.get_or_try_init()?.clone()),
|
||||||
|
None => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct WsUserAgent(pub String);
|
pub struct WsUserAgent(pub String);
|
||||||
|
|
||||||
|
@ -181,7 +192,10 @@ where
|
||||||
.borrow()
|
.borrow()
|
||||||
.try_borrow::<UnsafelyIgnoreCertificateErrors>()
|
.try_borrow::<UnsafelyIgnoreCertificateErrors>()
|
||||||
.and_then(|it| it.0.clone());
|
.and_then(|it| it.0.clone());
|
||||||
let root_cert_store = state.borrow().borrow::<WsRootStore>().0.clone();
|
let root_cert_store = state
|
||||||
|
.borrow()
|
||||||
|
.borrow::<WsRootStoreProvider>()
|
||||||
|
.get_or_try_init()?;
|
||||||
let user_agent = state.borrow().borrow::<WsUserAgent>().0.clone();
|
let user_agent = state.borrow().borrow::<WsUserAgent>().0.clone();
|
||||||
let uri: Uri = url.parse()?;
|
let uri: Uri = url.parse()?;
|
||||||
let mut request = Request::builder().method(Method::GET).uri(
|
let mut request = Request::builder().method(Method::GET).uri(
|
||||||
|
@ -525,7 +539,7 @@ deno_core::extension!(deno_websocket,
|
||||||
esm = [ "01_websocket.js", "02_websocketstream.js" ],
|
esm = [ "01_websocket.js", "02_websocketstream.js" ],
|
||||||
options = {
|
options = {
|
||||||
user_agent: String,
|
user_agent: String,
|
||||||
root_cert_store: Option<RootCertStore>,
|
root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
unsafely_ignore_certificate_errors: Option<Vec<String>>
|
unsafely_ignore_certificate_errors: Option<Vec<String>>
|
||||||
},
|
},
|
||||||
state = |state, options| {
|
state = |state, options| {
|
||||||
|
@ -533,7 +547,7 @@ deno_core::extension!(deno_websocket,
|
||||||
state.put(UnsafelyIgnoreCertificateErrors(
|
state.put(UnsafelyIgnoreCertificateErrors(
|
||||||
options.unsafely_ignore_certificate_errors,
|
options.unsafely_ignore_certificate_errors,
|
||||||
));
|
));
|
||||||
state.put::<WsRootStore>(WsRootStore(options.root_cert_store));
|
state.put::<WsRootStoreProvider>(WsRootStoreProvider(options.root_cert_store_provider));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ async fn main() -> Result<(), AnyError> {
|
||||||
extensions: vec![],
|
extensions: vec![],
|
||||||
startup_snapshot: None,
|
startup_snapshot: None,
|
||||||
unsafely_ignore_certificate_errors: None,
|
unsafely_ignore_certificate_errors: None,
|
||||||
root_cert_store: None,
|
root_cert_store_provider: None,
|
||||||
seed: None,
|
seed: None,
|
||||||
source_map_getter: None,
|
source_map_getter: None,
|
||||||
format_js_error_fn: None,
|
format_js_error_fn: None,
|
||||||
|
|
|
@ -8,7 +8,6 @@ use deno_core::op;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_fetch::data_url::DataUrl;
|
use deno_fetch::data_url::DataUrl;
|
||||||
use deno_fetch::reqwest;
|
|
||||||
use deno_web::BlobStore;
|
use deno_web::BlobStore;
|
||||||
use deno_websocket::DomExceptionNetworkError;
|
use deno_websocket::DomExceptionNetworkError;
|
||||||
use hyper::body::Bytes;
|
use hyper::body::Bytes;
|
||||||
|
@ -41,7 +40,7 @@ pub fn op_worker_sync_fetch(
|
||||||
let handle = state.borrow::<WebWorkerInternalHandle>().clone();
|
let handle = state.borrow::<WebWorkerInternalHandle>().clone();
|
||||||
assert_eq!(handle.worker_type, WebWorkerType::Classic);
|
assert_eq!(handle.worker_type, WebWorkerType::Classic);
|
||||||
|
|
||||||
let client = state.borrow::<reqwest::Client>().clone();
|
let client = deno_fetch::get_or_create_client_from_state(state)?;
|
||||||
|
|
||||||
// TODO(andreubotella) It's not good to throw an exception related to blob
|
// TODO(andreubotella) It's not good to throw an exception related to blob
|
||||||
// URLs when none of the script URLs use the blob scheme.
|
// URLs when none of the script URLs use the blob scheme.
|
||||||
|
|
|
@ -37,7 +37,7 @@ use deno_core::SourceMapGetter;
|
||||||
use deno_fs::StdFs;
|
use deno_fs::StdFs;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::sqlite::SqliteDbHandler;
|
use deno_kv::sqlite::SqliteDbHandler;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::RootCertStoreProvider;
|
||||||
use deno_web::create_entangled_message_port;
|
use deno_web::create_entangled_message_port;
|
||||||
use deno_web::BlobStore;
|
use deno_web::BlobStore;
|
||||||
use deno_web::MessagePort;
|
use deno_web::MessagePort;
|
||||||
|
@ -329,7 +329,7 @@ pub struct WebWorkerOptions {
|
||||||
pub extensions: Vec<Extension>,
|
pub extensions: Vec<Extension>,
|
||||||
pub startup_snapshot: Option<Snapshot>,
|
pub startup_snapshot: Option<Snapshot>,
|
||||||
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
||||||
pub root_cert_store: Option<RootCertStore>,
|
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
pub module_loader: Rc<dyn ModuleLoader>,
|
pub module_loader: Rc<dyn ModuleLoader>,
|
||||||
pub node_fs: Option<Arc<dyn deno_node::NodeFs>>,
|
pub node_fs: Option<Arc<dyn deno_node::NodeFs>>,
|
||||||
|
@ -407,7 +407,7 @@ impl WebWorker {
|
||||||
deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(
|
deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(
|
||||||
deno_fetch::Options {
|
deno_fetch::Options {
|
||||||
user_agent: options.bootstrap.user_agent.clone(),
|
user_agent: options.bootstrap.user_agent.clone(),
|
||||||
root_cert_store: options.root_cert_store.clone(),
|
root_cert_store_provider: options.root_cert_store_provider.clone(),
|
||||||
unsafely_ignore_certificate_errors: options
|
unsafely_ignore_certificate_errors: options
|
||||||
.unsafely_ignore_certificate_errors
|
.unsafely_ignore_certificate_errors
|
||||||
.clone(),
|
.clone(),
|
||||||
|
@ -418,7 +418,7 @@ impl WebWorker {
|
||||||
deno_cache::deno_cache::init_ops::<SqliteBackedCache>(create_cache),
|
deno_cache::deno_cache::init_ops::<SqliteBackedCache>(create_cache),
|
||||||
deno_websocket::deno_websocket::init_ops::<PermissionsContainer>(
|
deno_websocket::deno_websocket::init_ops::<PermissionsContainer>(
|
||||||
options.bootstrap.user_agent.clone(),
|
options.bootstrap.user_agent.clone(),
|
||||||
options.root_cert_store.clone(),
|
options.root_cert_store_provider.clone(),
|
||||||
options.unsafely_ignore_certificate_errors.clone(),
|
options.unsafely_ignore_certificate_errors.clone(),
|
||||||
),
|
),
|
||||||
deno_webstorage::deno_webstorage::init_ops(None).disable(),
|
deno_webstorage::deno_webstorage::init_ops(None).disable(),
|
||||||
|
@ -429,7 +429,7 @@ impl WebWorker {
|
||||||
),
|
),
|
||||||
deno_ffi::deno_ffi::init_ops::<PermissionsContainer>(unstable),
|
deno_ffi::deno_ffi::init_ops::<PermissionsContainer>(unstable),
|
||||||
deno_net::deno_net::init_ops::<PermissionsContainer>(
|
deno_net::deno_net::init_ops::<PermissionsContainer>(
|
||||||
options.root_cert_store.clone(),
|
options.root_cert_store_provider.clone(),
|
||||||
unstable,
|
unstable,
|
||||||
options.unsafely_ignore_certificate_errors.clone(),
|
options.unsafely_ignore_certificate_errors.clone(),
|
||||||
),
|
),
|
||||||
|
|
|
@ -33,7 +33,7 @@ use deno_core::SourceMapGetter;
|
||||||
use deno_fs::StdFs;
|
use deno_fs::StdFs;
|
||||||
use deno_io::Stdio;
|
use deno_io::Stdio;
|
||||||
use deno_kv::sqlite::SqliteDbHandler;
|
use deno_kv::sqlite::SqliteDbHandler;
|
||||||
use deno_tls::rustls::RootCertStore;
|
use deno_tls::RootCertStoreProvider;
|
||||||
use deno_web::BlobStore;
|
use deno_web::BlobStore;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ pub struct WorkerOptions {
|
||||||
/// V8 snapshot that should be loaded on startup.
|
/// V8 snapshot that should be loaded on startup.
|
||||||
pub startup_snapshot: Option<Snapshot>,
|
pub startup_snapshot: Option<Snapshot>,
|
||||||
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
|
||||||
pub root_cert_store: Option<RootCertStore>,
|
pub root_cert_store_provider: Option<Arc<dyn RootCertStoreProvider>>,
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
|
|
||||||
/// Implementation of `ModuleLoader` which will be
|
/// Implementation of `ModuleLoader` which will be
|
||||||
|
@ -163,7 +163,7 @@ impl Default for WorkerOptions {
|
||||||
cache_storage_dir: Default::default(),
|
cache_storage_dir: Default::default(),
|
||||||
broadcast_channel: Default::default(),
|
broadcast_channel: Default::default(),
|
||||||
source_map_getter: Default::default(),
|
source_map_getter: Default::default(),
|
||||||
root_cert_store: Default::default(),
|
root_cert_store_provider: Default::default(),
|
||||||
node_fs: Default::default(),
|
node_fs: Default::default(),
|
||||||
npm_resolver: Default::default(),
|
npm_resolver: Default::default(),
|
||||||
blob_store: Default::default(),
|
blob_store: Default::default(),
|
||||||
|
@ -228,7 +228,7 @@ impl MainWorker {
|
||||||
deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(
|
deno_fetch::deno_fetch::init_ops::<PermissionsContainer>(
|
||||||
deno_fetch::Options {
|
deno_fetch::Options {
|
||||||
user_agent: options.bootstrap.user_agent.clone(),
|
user_agent: options.bootstrap.user_agent.clone(),
|
||||||
root_cert_store: options.root_cert_store.clone(),
|
root_cert_store_provider: options.root_cert_store_provider.clone(),
|
||||||
unsafely_ignore_certificate_errors: options
|
unsafely_ignore_certificate_errors: options
|
||||||
.unsafely_ignore_certificate_errors
|
.unsafely_ignore_certificate_errors
|
||||||
.clone(),
|
.clone(),
|
||||||
|
@ -239,7 +239,7 @@ impl MainWorker {
|
||||||
deno_cache::deno_cache::init_ops::<SqliteBackedCache>(create_cache),
|
deno_cache::deno_cache::init_ops::<SqliteBackedCache>(create_cache),
|
||||||
deno_websocket::deno_websocket::init_ops::<PermissionsContainer>(
|
deno_websocket::deno_websocket::init_ops::<PermissionsContainer>(
|
||||||
options.bootstrap.user_agent.clone(),
|
options.bootstrap.user_agent.clone(),
|
||||||
options.root_cert_store.clone(),
|
options.root_cert_store_provider.clone(),
|
||||||
options.unsafely_ignore_certificate_errors.clone(),
|
options.unsafely_ignore_certificate_errors.clone(),
|
||||||
),
|
),
|
||||||
deno_webstorage::deno_webstorage::init_ops(
|
deno_webstorage::deno_webstorage::init_ops(
|
||||||
|
@ -252,7 +252,7 @@ impl MainWorker {
|
||||||
),
|
),
|
||||||
deno_ffi::deno_ffi::init_ops::<PermissionsContainer>(unstable),
|
deno_ffi::deno_ffi::init_ops::<PermissionsContainer>(unstable),
|
||||||
deno_net::deno_net::init_ops::<PermissionsContainer>(
|
deno_net::deno_net::init_ops::<PermissionsContainer>(
|
||||||
options.root_cert_store.clone(),
|
options.root_cert_store_provider.clone(),
|
||||||
unstable,
|
unstable,
|
||||||
options.unsafely_ignore_certificate_errors.clone(),
|
options.unsafely_ignore_certificate_errors.clone(),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue