fully replace http_req with reqwest

close #43
Should also help to either resolve or at least investigate seemingly random TLS & IO errors #64 #77
This commit is contained in:
mxve 2024-02-20 01:28:31 +01:00
parent 9de8543590
commit 02c3004231
6 changed files with 100 additions and 114 deletions

View File

@ -1,19 +1,21 @@
use semver::Version; use semver::Version;
pub fn latest_tag(owner: &str, repo: &str) -> String { pub async fn latest_tag(owner: &str, repo: &str) -> String {
let github_body = crate::http::get_body_string( let github_body = crate::http_async::get_body_string(
format!( format!(
"https://api.github.com/repos/{}/{}/releases/latest", "https://api.github.com/repos/{}/{}/releases/latest",
owner, repo owner, repo
) )
.as_str(), .as_str(),
); )
.await
.unwrap();
let github_json: serde_json::Value = serde_json::from_str(&github_body).unwrap(); let github_json: serde_json::Value = serde_json::from_str(&github_body).unwrap();
github_json["tag_name"].to_string().replace('"', "") github_json["tag_name"].to_string().replace('"', "")
} }
pub fn latest_version(owner: &str, repo: &str) -> Version { pub async fn latest_version(owner: &str, repo: &str) -> Version {
let tag = latest_tag(owner, repo).replace('v', ""); let tag = latest_tag(owner, repo).await.replace('v', "");
Version::parse(&tag).unwrap() Version::parse(&tag).unwrap()
} }

View File

@ -1,84 +0,0 @@
use crate::global;
use crate::misc;
use std::{fs, io::Write, path::Path, str};
pub fn get_body(url: &str) -> Vec<u8> {
let mut res: Vec<u8> = Vec::new();
match http_req::request::Request::new(&url.try_into().unwrap())
.header(
"User-Agent",
&format!(
"AlterWare Launcher | github.com/{}/{}",
global::GH_OWNER,
global::GH_REPO
),
)
.send(&mut res)
{
Ok(req) => {
if req.status_code() == http_req::response::StatusCode::new(302)
|| req.status_code() == http_req::response::StatusCode::new(301)
{
let location = req.headers().get("Location").unwrap().as_str();
return get_body(location);
}
if req.status_code() != http_req::response::StatusCode::new(200) {
misc::fatal_error(&format!(
"Could not get body from {}, got {}",
url,
req.status_code()
));
}
}
Err(e) => {
misc::fatal_error(&format!("Could not get body from {}, got:\n{}", url, e));
}
}
res
}
pub fn get_body_string(url: &str) -> String {
String::from_utf8(get_body(url)).unwrap()
}
pub fn download_file(url: &str, file_path: &Path) {
let body = get_body(url);
match fs::File::create(file_path) {
Ok(mut file) => match file.write_all(&body) {
Ok(_) => (),
Err(e) => {
misc::fatal_error(&format!(
"Could not write to file {}, got:\n{}",
file_path.to_str().unwrap(),
e
));
}
},
Err(e) => {
match e.kind() {
std::io::ErrorKind::NotFound => {
fs::create_dir_all(file_path.parent().unwrap()).unwrap();
return download_file(url, file_path);
}
std::io::ErrorKind::PermissionDenied => {
misc::fatal_error(&format!(
"Permission to {} denied.\n Please try:\n 1. Running the launcher as administrator.\n 2. Manually deleting the last downloaded file.\n 3. If your game is in the program files directory try moving it to another location.\n 4. Create an exception/exclusion in your Anti-Virus Software for either the last downloaded file or the entire game directory.\n\n\n{}",
file_path.to_str().unwrap(),
e
));
}
_ => (),
}
misc::fatal_error(&format!(
"Could not create file {}, got:\n{}",
file_path.to_str().unwrap(),
e
));
}
}
}

View File

@ -10,7 +10,7 @@ use reqwest::Client;
use crate::misc; use crate::misc;
pub async fn download_file( pub async fn download_file_progress(
client: &Client, client: &Client,
pb: &ProgressBar, pb: &ProgressBar,
url: &str, url: &str,
@ -58,3 +58,65 @@ pub async fn download_file(
pb.set_message(String::default()); pb.set_message(String::default());
Ok(()) Ok(())
} }
pub async fn download_file(url: &str, path: &PathBuf) -> Result<(), String> {
let client = Client::new();
match client
.get(url)
.header(
"User-Agent",
&format!(
"AlterWare Launcher | github.com/{}/{}",
crate::global::GH_OWNER,
crate::global::GH_REPO
),
)
.send()
.await
{
Ok(res) => {
let body = res.bytes().await.or(Err("Failed to download file"))?;
let mut file = File::create(path).or(Err("Failed to create file"))?;
file.write_all(&body).or(Err("Failed to write to file"))?;
Ok(())
}
Err(e) => {
misc::fatal_error(&format!(
"Could not download file from {}, got:\n{}",
url, e
));
Err("Could not download file".to_string())
}
}
}
pub async fn get_body(url: &str) -> Result<Vec<u8>, String> {
let client = Client::new();
match client
.get(url)
.header(
"User-Agent",
&format!(
"AlterWare Launcher | github.com/{}/{}",
crate::global::GH_OWNER,
crate::global::GH_REPO
),
)
.send()
.await
{
Ok(res) => {
let body = res.bytes().await.or(Err("Failed to get body"))?;
Ok(body.to_vec())
}
Err(e) => {
misc::fatal_error(&format!("Could not get body from {}, got:\n{}", url, e));
Err("Could not get body".to_string())
}
}
}
pub async fn get_body_string(url: &str) -> Result<String, String> {
let body = get_body(url).await?;
Ok(String::from_utf8(body).unwrap())
}

View File

@ -1,6 +1,6 @@
use crate::github; use crate::github;
use crate::global::*; use crate::global::*;
use crate::http; use crate::http_async;
use crate::misc; use crate::misc;
use colored::*; use colored::*;
@ -14,12 +14,12 @@ pub fn local_revision(dir: &Path) -> u16 {
} }
} }
pub fn remote_revision() -> u16 { pub async fn remote_revision() -> u16 {
misc::rev_to_int(&github::latest_tag(GH_IW4X_OWNER, GH_IW4X_REPO)) misc::rev_to_int(&github::latest_tag(GH_IW4X_OWNER, GH_IW4X_REPO).await)
} }
pub fn update(dir: &Path) { pub async fn update(dir: &Path) {
let remote = remote_revision(); let remote = remote_revision().await;
let local = local_revision(dir); let local = local_revision(dir);
if remote <= local && dir.join("iw4x.dll").exists() { if remote <= local && dir.join("iw4x.dll").exists() {
@ -39,12 +39,14 @@ pub fn update(dir: &Path) {
"Downloading".bright_yellow(), "Downloading".bright_yellow(),
misc::cute_path(&dir.join("iw4x.dll")) misc::cute_path(&dir.join("iw4x.dll"))
); );
http::download_file( http_async::download_file(
&format!( &format!(
"{}/download/iw4x.dll", "{}/download/iw4x.dll",
github::latest_release_url(GH_IW4X_OWNER, GH_IW4X_REPO) github::latest_release_url(GH_IW4X_OWNER, GH_IW4X_REPO)
), ),
&dir.join("iw4x.dll"), &dir.join("iw4x.dll"),
); )
.await
.unwrap();
fs::write(dir.join(".iw4xrevision"), format!("r{}", remote)).unwrap(); fs::write(dir.join(".iw4xrevision"), format!("r{}", remote)).unwrap();
} }

View File

@ -1,7 +1,6 @@
mod config; mod config;
mod github; mod github;
mod global; mod global;
mod http;
mod http_async; mod http_async;
mod iw4x; mod iw4x;
mod misc; mod misc;
@ -271,7 +270,7 @@ async fn update_dir(
fs::create_dir_all(parent).unwrap(); fs::create_dir_all(parent).unwrap();
} }
} }
http_async::download_file( http_async::download_file_progress(
&client, &client,
pb, pb,
&format!("{}/{}", master_url, file.name), &format!("{}/{}", master_url, file.name),
@ -292,15 +291,16 @@ async fn update(
force: bool, force: bool,
skip_iw4x_sp: Option<bool>, skip_iw4x_sp: Option<bool>,
master_url: &String, master_url: &String,
ignore_required_files: Option<bool> ignore_required_files: Option<bool>,
) { ) {
let skip_iw4x_sp = skip_iw4x_sp.unwrap_or(false); let skip_iw4x_sp = skip_iw4x_sp.unwrap_or(false);
let ignore_required_files = ignore_required_files.unwrap_or(false); let ignore_required_files = ignore_required_files.unwrap_or(false);
let cdn_info: Vec<CdnFile> = serde_json::from_str(&http::get_body_string( let res = http_async::get_body_string(format!("{}/files.json", master_url).as_str())
format!("{}/files.json", master_url).as_str(), .await
))
.unwrap(); .unwrap();
println!("{}", res);
let cdn_info: Vec<CdnFile> = serde_json::from_str(&res).unwrap();
if !ignore_required_files && !game.required_files_exist(dir) { if !ignore_required_files && !game.required_files_exist(dir) {
println!( println!(
@ -324,7 +324,7 @@ async fn update(
} }
if game.engine == "iw4" { if game.engine == "iw4" {
iw4x::update(dir); iw4x::update(dir).await;
let iw4x_dirs = vec!["iw4x", "zone/patch"]; let iw4x_dirs = vec!["iw4x", "zone/patch"];
for d in &iw4x_dirs { for d in &iw4x_dirs {
@ -558,7 +558,7 @@ async fn main() {
}; };
if !arg_bool(&args, "--skip-launcher-update") && !cfg.skip_self_update { if !arg_bool(&args, "--skip-launcher-update") && !cfg.skip_self_update {
self_update::run(cfg.update_only); self_update::run(cfg.update_only).await;
} else { } else {
arg_remove(&mut args, "--skip-launcher-update"); arg_remove(&mut args, "--skip-launcher-update");
} }
@ -593,7 +593,9 @@ async fn main() {
cfg.args = String::default(); cfg.args = String::default();
} }
let games_json = http::get_body_string(format!("{}/games.json", master_url).as_str()); let games_json = http_async::get_body_string(format!("{}/games.json", master_url).as_str())
.await
.unwrap();
let games: Vec<Game> = serde_json::from_str(&games_json).unwrap(); let games: Vec<Game> = serde_json::from_str(&games_json).unwrap();
let mut game: String = String::new(); let mut game: String = String::new();

View File

@ -5,9 +5,9 @@ use semver::Version;
#[cfg(not(windows))] #[cfg(not(windows))]
use std::{thread, time}; use std::{thread, time};
pub fn self_update_available() -> bool { pub async fn self_update_available() -> bool {
let current_version: Version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap(); let current_version: Version = Version::parse(env!("CARGO_PKG_VERSION")).unwrap();
let latest_version = github::latest_version(GH_OWNER, GH_REPO); let latest_version = github::latest_version(GH_OWNER, GH_REPO).await;
current_version < latest_version current_version < latest_version
} }
@ -39,10 +39,10 @@ pub fn restart() -> std::io::Error {
} }
#[cfg(windows)] #[cfg(windows)]
pub fn run(update_only: bool) { pub async fn run(update_only: bool) {
use std::{fs, path::PathBuf}; use std::{fs, path::PathBuf};
use crate::http; use crate::http_async;
use crate::misc; use crate::misc;
let working_dir = std::env::current_dir().unwrap(); let working_dir = std::env::current_dir().unwrap();
@ -62,7 +62,7 @@ pub fn run(update_only: bool) {
} }
} }
if self_update_available() { if self_update_available().await {
println!("Performing launcher self-update."); println!("Performing launcher self-update.");
println!( println!(
"If you run into any issues, please download the latest version at {}", "If you run into any issues, please download the latest version at {}",
@ -82,14 +82,16 @@ pub fn run(update_only: bool) {
"alterware-launcher.exe" "alterware-launcher.exe"
}; };
http::download_file( http_async::download_file(
&format!( &format!(
"{}/download/{}", "{}/download/{}",
github::latest_release_url(GH_OWNER, GH_REPO), github::latest_release_url(GH_OWNER, GH_REPO),
launcher_name launcher_name
), ),
&file_path, &file_path,
); )
.await
.unwrap();
if !file_path.exists() { if !file_path.exists() {
println!("Failed to download launcher update."); println!("Failed to download launcher update.");