diff --git a/src/archive/zip.rs b/src/archive/zip.rs index 37a69a365..4634b5a9a 100644 --- a/src/archive/zip.rs +++ b/src/archive/zip.rs @@ -86,8 +86,11 @@ mod tests { #[test_log::test] fn test_zip_extraction() { let temp_dir = &tempfile::tempdir().expect("Can't create a temp directory"); - let response = crate::http::get("https://nodejs.org/dist/v12.0.0/node-v12.0.0-win-x64.zip") - .expect("Can't make request to Node v12.0.0 zip file"); + let response = crate::http::get( + "https://nodejs.org/dist/v12.0.0/node-v12.0.0-win-x64.zip", + None, + ) + .expect("Can't make request to Node v12.0.0 zip file"); Box::new(Zip::new(response)) .extract_into(temp_dir.as_ref()) .expect("Can't unzip files"); diff --git a/src/commands/install.rs b/src/commands/install.rs index e51ac0b8b..90a72ed56 100644 --- a/src/commands/install.rs +++ b/src/commands/install.rs @@ -85,8 +85,11 @@ impl Command for Install { return Err(Error::UninstallableVersion { version: v }); } UserVersion::Full(Version::Lts(lts_type)) => { - let available_versions: Vec<_> = remote_node_index::list(&config.node_dist_mirror) - .map_err(|source| Error::CantListRemoteVersions { source })?; + let available_versions: Vec<_> = remote_node_index::list( + &config.node_dist_mirror, + &config.node_dist_mirror_token, + ) + .map_err(|source| Error::CantListRemoteVersions { source })?; let picked_version = lts_type .pick_latest(&available_versions) .ok_or_else(|| Error::CantFindRelevantLts { @@ -102,8 +105,11 @@ impl Command for Install { picked_version } UserVersion::Full(Version::Latest) => { - let available_versions: Vec<_> = remote_node_index::list(&config.node_dist_mirror) - .map_err(|source| Error::CantListRemoteVersions { source })?; + let available_versions: Vec<_> = remote_node_index::list( + &config.node_dist_mirror, + &config.node_dist_mirror_token, + ) + .map_err(|source| Error::CantListRemoteVersions { source })?; let picked_version = available_versions .last() .ok_or(Error::CantFindLatest)? @@ -117,11 +123,14 @@ impl Command for Install { picked_version } current_version => { - let available_versions: Vec<_> = remote_node_index::list(&config.node_dist_mirror) - .map_err(|source| Error::CantListRemoteVersions { source })? - .drain(..) - .map(|x| x.version) - .collect(); + let available_versions: Vec<_> = remote_node_index::list( + &config.node_dist_mirror, + &config.node_dist_mirror_token, + ) + .map_err(|source| Error::CantListRemoteVersions { source })? + .drain(..) + .map(|x| x.version) + .collect(); current_version .to_version(&available_versions, config) @@ -147,6 +156,7 @@ impl Command for Install { match install_node_dist( &version, &config.node_dist_mirror, + &config.node_dist_mirror_token, config.installations_dir(), safe_arch, show_progress, @@ -306,8 +316,8 @@ mod tests { .apply(&config) .expect("Can't install"); - let available_versions: Vec<_> = - remote_node_index::list(&config.node_dist_mirror).expect("Can't get node version list"); + let available_versions: Vec<_> = remote_node_index::list(&config.node_dist_mirror, "") + .expect("Can't get node version list"); let latest_version = available_versions.last().unwrap().version.clone(); assert!(config.installations_dir().exists()); diff --git a/src/commands/ls_remote.rs b/src/commands/ls_remote.rs index 3da0dd922..43e83149a 100644 --- a/src/commands/ls_remote.rs +++ b/src/commands/ls_remote.rs @@ -51,7 +51,8 @@ impl super::command::Command for LsRemote { type Error = Error; fn apply(self, config: &FnmConfig) -> Result<(), Self::Error> { - let mut all_versions = remote_node_index::list(&config.node_dist_mirror)?; + let mut all_versions = + remote_node_index::list(&config.node_dist_mirror, &config.node_dist_mirror_token)?; if let Some(lts) = &self.lts { match lts { diff --git a/src/config.rs b/src/config.rs index fbaf3a3af..ca8f94551 100644 --- a/src/config.rs +++ b/src/config.rs @@ -17,6 +17,15 @@ pub struct FnmConfig { )] pub node_dist_mirror: Url, + #[clap( + long, + env = "FNM_NODE_DIST_MIRROR_TOKEN", + default_value_t, + global = true, + hide_env_values = true + )] + pub node_dist_mirror_token: String, + /// The root directory of fnm installations. #[clap( long = "fnm-dir", @@ -104,6 +113,7 @@ impl Default for FnmConfig { fn default() -> Self { Self { node_dist_mirror: Url::parse("https://nodejs.org/dist/").unwrap(), + node_dist_mirror_token: String::new(), base_dir: None, multishell_path: None, log_level: LogLevel::Info, diff --git a/src/downloader.rs b/src/downloader.rs index 6fb6b6c25..795b8e1d8 100644 --- a/src/downloader.rs +++ b/src/downloader.rs @@ -70,6 +70,7 @@ fn download_url(base_url: &Url, version: &Version, arch: Arch, ext: &str) -> Url pub fn install_node_dist>( version: &Version, node_dist_mirror: &Url, + node_dist_mirror_token: &str, installations_dir: P, arch: Arch, show_progress: bool, @@ -93,7 +94,7 @@ pub fn install_node_dist>( let ext = extract.file_extension(); let url = download_url(node_dist_mirror, version, arch, ext); debug!("Going to call for {}", &url); - let response = crate::http::get(url.as_str())?; + let response = crate::http::get(url.as_str(), Some(node_dist_mirror_token))?; if !response.status().is_success() { continue; @@ -175,7 +176,7 @@ mod tests { let version = Version::parse("12.0.0").unwrap(); let arch = Arch::X64; let node_dist_mirror = Url::parse("https://nodejs.org/dist/").unwrap(); - install_node_dist(&version, &node_dist_mirror, path, arch, false) + install_node_dist(&version, &node_dist_mirror, "", path, arch, false) .expect("Can't install Node 12"); let mut location_path = path.join(version.v_str()).join("installation"); diff --git a/src/http.rs b/src/http.rs index 57d23a3a1..ffea784c6 100644 --- a/src/http.rs +++ b/src/http.rs @@ -10,10 +10,17 @@ use reqwest::{blocking::Client, IntoUrl}; pub struct Error(#[from] reqwest::Error); pub type Response = reqwest::blocking::Response; -pub fn get(url: impl IntoUrl) -> Result { - Ok(Client::new() +pub fn get(url: impl IntoUrl, token: Option<&str>) -> Result { + let mut client = Client::new() .get(url) // Some sites require a user agent. - .header("User-Agent", concat!("fnm ", env!("CARGO_PKG_VERSION"))) - .send()?) + .header("User-Agent", concat!("fnm ", env!("CARGO_PKG_VERSION"))); + + if let Some(token) = token { + if !token.is_empty() { + client = client.header("Authorization", format!("Bearer {}", token)); + } + } + + Ok(client.send()?) } diff --git a/src/remote_node_index.rs b/src/remote_node_index.rs index 9c4016ac5..90140f652 100644 --- a/src/remote_node_index.rs +++ b/src/remote_node_index.rs @@ -81,10 +81,10 @@ pub enum Error { /// ```rust /// use crate::remote_node_index::list; /// ``` -pub fn list(base_url: &Url) -> Result, Error> { +pub fn list(base_url: &Url, token: &str) -> Result, Error> { let base_url = base_url.as_str().trim_end_matches('/'); let index_json_url = format!("{base_url}/index.json"); - let resp = crate::http::get(&index_json_url)? + let resp = crate::http::get(&index_json_url, Some(token))? .error_for_status() .map_err(crate::http::Error::from)?; let text = resp.text().map_err(crate::http::Error::from)?; @@ -103,7 +103,7 @@ mod tests { fn test_list() { let base_url = Url::parse("https://nodejs.org/dist").unwrap(); let expected_version = Version::parse("12.0.0").unwrap(); - let mut versions = list(&base_url).expect("Can't get HTTP data"); + let mut versions = list(&base_url, "").expect("Can't get HTTP data"); assert_eq!( versions .drain(..)