From 62cfd9adbbe1687275ab752ffd43edbae10d4000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jesper=20H=C3=A5kansson?= Date: Sun, 26 May 2019 22:15:00 +0200 Subject: [PATCH] fix: Rate limit version check if the request fails fix: Output warning if version check fails --- src/build/mod.rs | 7 +--- src/main.rs | 18 +++++++--- src/manifest/mod.rs | 85 +++++++++++++++++++++++++++++---------------- src/stamps.rs | 10 +++--- 4 files changed, 76 insertions(+), 44 deletions(-) diff --git a/src/build/mod.rs b/src/build/mod.rs index 4e5bb112..6a97035b 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -62,12 +62,7 @@ fn rustc_minor_version() -> Option { /// Checks and returns local and latest versions of wasm-pack pub fn check_wasm_pack_versions() -> Result { match wasm_pack_local_version() { - Some(local) => { - match Crate::return_wasm_pack_latest_version() { - Some(latest) => Ok(WasmPackVersion {local, latest}), - None => Ok(WasmPackVersion {local, latest: "".to_string()}) - } - }, + Some(local) => Ok(WasmPackVersion {local, latest: Crate::return_wasm_pack_latest_version()?.unwrap_or_else(|| "".to_string())}), None => bail!("We can't figure out what your wasm-pack version is, make sure the installation path is correct.") } } diff --git a/src/main.rs b/src/main.rs index ad9b152a..7fbf4671 100644 --- a/src/main.rs +++ b/src/main.rs @@ -23,17 +23,21 @@ use wasm_pack::{ mod installer; -fn background_check_for_updates() -> mpsc::Receiver { +fn background_check_for_updates() -> mpsc::Receiver> { let (sender, receiver) = mpsc::channel(); let _detached_thread = thread::spawn(move || { - if let Ok(wasm_pack_version) = build::check_wasm_pack_versions() { + let wasm_pack_version = build::check_wasm_pack_versions(); + + if let Ok(wasm_pack_version) = wasm_pack_version { if !wasm_pack_version.local.is_empty() && !wasm_pack_version.latest.is_empty() && wasm_pack_version.local != wasm_pack_version.latest { - let _ = sender.send(wasm_pack_version); + let _ = sender.send(Ok(wasm_pack_version)); } + } else { + let _ = sender.send(wasm_pack_version); } }); @@ -79,8 +83,12 @@ fn run() -> Result<(), failure::Error> { run_wasm_pack(args.cmd)?; if let Ok(wasm_pack_version) = wasm_pack_version.try_recv() { - PBAR.warn(&format!("There's a newer version of wasm-pack available, the new version is: {}, you are using: {}. \ - To update, navigate to: https://rustwasm.github.io/wasm-pack/installer/", wasm_pack_version.latest, wasm_pack_version.local)); + match wasm_pack_version { + Ok(wasm_pack_version) => + PBAR.warn(&format!("There's a newer version of wasm-pack available, the new version is: {}, you are using: {}. \ + To update, navigate to: https://rustwasm.github.io/wasm-pack/installer/", wasm_pack_version.latest, wasm_pack_version.local)), + Err(err) => PBAR.warn(&format!("{}", err)) + } } Ok(()) diff --git a/src/manifest/mod.rs b/src/manifest/mod.rs index 03384749..0caaf420 100644 --- a/src/manifest/mod.rs +++ b/src/manifest/mod.rs @@ -149,39 +149,49 @@ struct CrateInformation { impl Crate { /// Returns latest wasm-pack version - pub fn return_wasm_pack_latest_version() -> Option { + pub fn return_wasm_pack_latest_version() -> Result, failure::Error> { let current_time = chrono::offset::Local::now(); + let old_metadata_file = Self::return_wasm_pack_file(); - Self::return_wasm_pack_file() - .and_then(|contents| { - let last_updated = Self::return_stamp_file_value(&contents, "created") + match old_metadata_file { + Some(ref file_contents) => { + let last_updated = Self::return_stamp_file_value(&file_contents, "created") .and_then(|t| DateTime::parse_from_str(t.as_str(), "%+").ok()); - Self::return_stamp_file_value(&contents, "version").and_then(|v| { - last_updated.and_then(|last_updated| { + last_updated + .map(|last_updated| { if current_time.signed_duration_since(last_updated).num_hours() > 24 { - Self::return_api_call_result(current_time) + Self::return_api_call_result(current_time).map(Some) } else { - Some(v) + Ok(Self::return_stamp_file_value(&file_contents, "version")) } }) - }) - }) - .map_or(Self::return_api_call_result(current_time), |value| { - Some(value) - }) + .unwrap_or_else(|| Ok(None)) + } + None => Self::return_api_call_result(current_time).map(Some), + } } - fn return_api_call_result(current_time: DateTime) -> Option { - Self::return_latest_wasm_pack_version().and_then(|v| { - Self::override_stamp_file(current_time, &v).ok(); - Some(v) - }) + fn return_api_call_result( + current_time: DateTime, + ) -> Result { + let version = Self::return_latest_wasm_pack_version(); + + // We always override the stamp file with the current time because we don't + // want to hit the API all the time if it fails. It should follow the same + // "policy" as the success. This means that the 24 hours rate limiting + // will be active regardless if the check succeeded or failed. + match version { + Ok(ref version) => Self::override_stamp_file(current_time, Some(&version)).ok(), + Err(_) => Self::override_stamp_file(current_time, None).ok(), + }; + + version } fn override_stamp_file( current_time: DateTime, - version: &str, + version: Option<&str>, ) -> Result<(), failure::Error> { let path = env::current_exe()?; @@ -194,7 +204,11 @@ impl Crate { file.set_len(0)?; - write!(file, "created {:?}\nversion {}", current_time, version)?; + write!(file, "created {:?}", current_time)?; + + if let Some(version) = version { + write!(file, "\nversion {}", version)?; + } Ok(()) } @@ -210,11 +224,8 @@ impl Crate { } /// Returns wasm-pack latest version (if it's received) by executing check_wasm_pack_latest_version function. - fn return_latest_wasm_pack_version() -> Option { - if let Ok(crt) = Self::check_wasm_pack_latest_version() { - return Some(crt.crt.max_version); - } - None + fn return_latest_wasm_pack_version() -> Result { + Self::check_wasm_pack_latest_version().map(|crt| crt.crt.max_version) } /// Read the stamp file and return value assigned to a certain key. @@ -229,18 +240,34 @@ impl Crate { /// Call to the crates.io api and return the latest version of `wasm-pack` fn check_wasm_pack_latest_version() -> Result { + let url = "https://crates.io/api/v1/crates/wasm-pack"; + let mut easy = easy::Easy2::new(Collector(Vec::new())); + easy.useragent(&format!( "wasm-pack/{} ({})", WASM_PACK_VERSION.unwrap_or_else(|| "unknown"), WASM_PACK_REPO_URL ))?; + + easy.url(url)?; easy.get(true)?; - easy.url("https://crates.io/api/v1/crates/wasm-pack")?; easy.perform()?; - let contents = easy.get_ref(); - let result = String::from_utf8_lossy(&contents.0); - Ok(serde_json::from_str(result.into_owned().as_str())?) + + let status_code = easy.response_code()?; + + if 200 <= status_code && status_code < 300 { + let contents = easy.get_ref(); + let result = String::from_utf8_lossy(&contents.0); + + Ok(serde_json::from_str(result.into_owned().as_str())?) + } else { + bail!( + "Received a bad HTTP status code ({}) when checking for newer wasm-pack version at: {}", + status_code, + url + ) + } } } diff --git a/src/stamps.rs b/src/stamps.rs index 4fee932c..62cd2e11 100644 --- a/src/stamps.rs +++ b/src/stamps.rs @@ -24,10 +24,12 @@ pub fn save_stamp_value( ) -> Result<(), failure::Error> { let mut json = read_stamps_file_to_json().unwrap_or_else(|_| serde_json::Map::new().into()); - let stamps = json - .as_object_mut() - .ok_or_else(|| failure::err_msg("stamps file doesn't contain JSON object"))?; - stamps.insert(key.into(), value.as_ref().into()); + { + let stamps = json + .as_object_mut() + .ok_or_else(|| failure::err_msg("stamps file doesn't contain JSON object"))?; + stamps.insert(key.into(), value.as_ref().into()); + } write_to_stamps_file(json) }