Skip to content

Commit

Permalink
optimized usage of HTTP client
Browse files Browse the repository at this point in the history
- It now uses a user-agent indentifying itself
- The launcher now checks if it can access api.liquidbounce.net on startup. If not it will show a alert message.
- Reduced code duplication
  • Loading branch information
1zun4 committed Jun 4, 2023
1 parent 31dbadc commit 655a5f6
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 24 deletions.
7 changes: 5 additions & 2 deletions src-tauri/src/app/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};
use serde::de::DeserializeOwned;

use crate::HTTP_CLIENT;
use crate::utils::get_maven_artifact_path;

/// API endpoint url
Expand All @@ -31,7 +32,8 @@ impl ContentDelivery {

/// Request JSON formatted data from content delivery
pub async fn request_from_content_delivery<T: DeserializeOwned>(file: &str) -> Result<T> {
Ok(reqwest::get(format!("{}/{}/{}", CONTENT_DELIVERY, CONTENT_FOLDER, file)).await?
Ok(HTTP_CLIENT.get(format!("{}/{}/{}", CONTENT_DELIVERY, CONTENT_FOLDER, file))
.send().await?
.error_for_status()?
.json::<T>()
.await?
Expand Down Expand Up @@ -107,7 +109,8 @@ impl ApiEndpoints {

/// Request JSON formatted data from launcher API
pub async fn request_from_endpoint<T: DeserializeOwned>(endpoint: &str) -> Result<T> {
Ok(reqwest::get(format!("{}/{}/{}", LAUNCHER_API, LAUNCHER_API_VERSION, endpoint)).await?
Ok(HTTP_CLIENT.get(format!("{}/{}/{}", LAUNCHER_API, LAUNCHER_API_VERSION, endpoint))
.send().await?
.error_for_status()?
.json::<T>()
.await?
Expand Down
13 changes: 12 additions & 1 deletion src-tauri/src/app/gui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{sync::{Arc, Mutex}, thread};
use tracing::{error, info};
use tauri::{Manager, Window};

use crate::{LAUNCHER_DIRECTORY, minecraft::{launcher::{LauncherData, LaunchingParameter}, prelauncher, progress::ProgressUpdate, service::{self, Account}}};
use crate::{LAUNCHER_DIRECTORY, minecraft::{launcher::{LauncherData, LaunchingParameter}, prelauncher, progress::ProgressUpdate, service::{self, Account}}, HTTP_CLIENT};
use crate::app::api::{Branches, Changelog, ContentDelivery, News};
use crate::utils::percentage_of_total_memory;

Expand All @@ -17,6 +17,16 @@ struct AppState {
runner_instance: Arc<Mutex<Option<RunnerInstance>>>
}

#[tauri::command]
async fn check_online_status() -> Result<(), String> {
HTTP_CLIENT.get("https://api.liquidbounce.net/")
.send().await
.map_err(|e| format!("unable to connect to api.liquidbounce.net: {:}", e))?
.error_for_status()
.map_err(|e| format!("api.liquidbounce.net returned an error: {:}", e))?;
Ok(())
}

#[tauri::command]
fn open_url(url: &str) -> Result<(), String> {
open::that(url)
Expand Down Expand Up @@ -321,6 +331,7 @@ pub fn gui_main() {
})
.invoke_handler(tauri::generate_handler![
open_url,
check_online_status,
get_options,
store_options,
request_branches,
Expand Down
17 changes: 17 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::{fs, io};
use once_cell::sync::Lazy;
use anyhow::Result;
use directories::ProjectDirs;
use reqwest::Client;
use tracing::{debug};
use tracing_subscriber::layer::SubscriberExt;

Expand All @@ -26,6 +27,22 @@ static LAUNCHER_DIRECTORY: Lazy<ProjectDirs> = Lazy::new(|| {
}
});

static APP_USER_AGENT: &str = concat!(
env!("CARGO_PKG_NAME"),
"/",
env!("CARGO_PKG_VERSION"),
);

/// HTTP Client with launcher agent
static HTTP_CLIENT: Lazy<Client> = Lazy::new(|| {
let client = reqwest::ClientBuilder::new()
.user_agent(APP_USER_AGENT)
.build()
.unwrap_or_else(|_| Client::new());

client
});

pub fn main() -> Result<()> {
use tracing_subscriber::{fmt, EnvFilter};

Expand Down
6 changes: 3 additions & 3 deletions src-tauri/src/minecraft/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tokio::fs;
use uuid::Uuid;

use crate::error::AuthenticationError;
use crate::LAUNCHER_DIRECTORY;
use crate::{LAUNCHER_DIRECTORY, HTTP_CLIENT};

const MOJANG_AUTH_SERVER: &str = "https://authserver.mojang.com";
pub(crate) const AZURE_CLIENT_ID: &str = "0add8caf-2cc6-4546-b798-c3d171217dd9";
Expand Down Expand Up @@ -155,8 +155,8 @@ impl Account {
pub async fn name_to_uuid(name: &String) -> Result<String> {
// https://api.mojang.com/users/profiles/minecraft/<username>

let uuid_response = reqwest::get(format!("https://api.mojang.com/users/profiles/minecraft/{}", name))
.await?
let uuid_response = HTTP_CLIENT.get(format!("https://api.mojang.com/users/profiles/minecraft/{}", name))
.send().await?
.json::<UuidResponse>().await?;

match uuid_response {
Expand Down
33 changes: 16 additions & 17 deletions src-tauri/src/minecraft/version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{Deserialize, Deserializer, de::{self, MapAccess, Visitor}};
use void::Void;
use os_info::{Bitness, Info};
use std::collections::HashSet;
use crate::error::LauncherError;
use crate::{error::LauncherError, HTTP_CLIENT, utils::download_file_untracked};
use crate::utils::{get_maven_artifact_path, sha1sum};
use std::sync::Arc;
use crate::minecraft::launcher::LaunchingParameter;
Expand All @@ -23,7 +23,12 @@ pub struct VersionManifest {
impl VersionManifest {

pub async fn download() -> Result<Self> {
Ok(reqwest::get("https://launchermeta.mojang.com/mc/game/version_manifest.json").await?.error_for_status()?.json::<VersionManifest>().await?)
let response = HTTP_CLIENT.get("https://launchermeta.mojang.com/mc/game/version_manifest.json")
.send().await?
.error_for_status()?;
let manifest = response.json::<VersionManifest>().await?;

Ok(manifest)
}

}
Expand Down Expand Up @@ -193,7 +198,7 @@ pub struct V21ArgumentDeclaration {
impl VersionProfile {
pub async fn load(url: &String) -> Result<Self> {
dbg!(url);
Ok(reqwest::get(url).await?.error_for_status()?.json::<VersionProfile>().await?)
Ok(HTTP_CLIENT.get(url).send().await?.error_for_status()?.json::<VersionProfile>().await?)
}
}

Expand Down Expand Up @@ -298,7 +303,8 @@ impl AssetIndexLocation {

if !asset_index.exists() {
info!("Downloading assets index of {}", self.id);
fs::write(&asset_index, reqwest::get(&self.url).await?.error_for_status()?.bytes().await?).await?;
download_file_untracked(&self.url, &asset_index).await?;
info!("Downloaded {}", self.url);
}

let content = &*fs::read(&asset_index).await?;
Expand Down Expand Up @@ -334,8 +340,7 @@ impl AssetObject {
progress.progress_update(ProgressUpdate::set_label(format!("Downloading asset object {}", self.hash)));

info!("Downloading {}", self.hash);
let os = reqwest::get(&*format!("https://resources.download.minecraft.net/{}/{}", &self.hash[0..2], &self.hash)).await?.error_for_status()?.bytes().await?;
fs::write(asset_path, os).await?;
download_file_untracked(&*format!("https://resources.download.minecraft.net/{}/{}", &self.hash[0..2], &self.hash), asset_path).await?;
info!("Downloaded {}", self.hash);

Ok(true)
Expand Down Expand Up @@ -370,10 +375,8 @@ pub struct Download {
impl Download {

pub async fn download(&self, path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref().to_owned();
let os = reqwest::get(&self.url).await?.error_for_status()?.bytes().await?;
fs::write(path, os).await?;
info!("downloaded {}", self.url);
download_file_untracked(&self.url, path).await?;
info!("Downloaded {}", self.url);
Ok(())
}

Expand Down Expand Up @@ -486,8 +489,8 @@ impl From<&LibraryArtifact> for LibraryDownloadInfo {
impl LibraryDownloadInfo {

async fn fetch_sha1(&self) -> Result<String> {
reqwest::get(&format!("{}{}", &self.url, ".sha1"))
.await?
HTTP_CLIENT.get(&format!("{}{}", &self.url, ".sha1"))
.send().await?
.error_for_status()?
.text()
.await
Expand Down Expand Up @@ -555,11 +558,7 @@ impl LibraryDownloadInfo {
// Download library
progress.progress_update(ProgressUpdate::set_label(format!("Downloading library {}", name)));

let os = reqwest::get(&self.url).await?
.error_for_status()?
.bytes()
.await?;
fs::write(&library_path, os).await?;
download_file_untracked(&self.url, &library_path).await?;
info!("Downloaded {}", self.url);

// After downloading, check sha1
Expand Down
21 changes: 20 additions & 1 deletion src-tauri/src/utils/download.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,29 @@
use std::path::Path;

use tokio::fs;
use tracing::debug;
use anyhow::Result;

use crate::HTTP_CLIENT;

/// Download file using HTTP_CLIENT without any progress tracking
pub async fn download_file_untracked(url: &str, path: impl AsRef<Path>) -> Result<()> {
let path = path.as_ref().to_owned();
let response = HTTP_CLIENT.get(url)
.send().await?
.error_for_status()?;

let content = response.bytes().await?;
fs::write(path, content).await?;
Ok(())
}

pub async fn download_file<F>(url: &str, on_progress: F) -> Result<Vec<u8>> where F : Fn(u64, u64) {
debug!("Downloading file {:?}", url);

let mut response = reqwest::get(url.trim()).await?.error_for_status()?;
let mut response = HTTP_CLIENT.get(url.trim())
.send().await?
.error_for_status()?;

debug!("Response received from url");

Expand Down
8 changes: 8 additions & 0 deletions src/lib/Window.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import LoginScreen from "./login/LoginScreen.svelte";
import MainScreen from "./main/MainScreen.svelte";
import { once } from "@tauri-apps/api/event";
import { appWindow } from "@tauri-apps/api/window";
// Load options from file
let options;
Expand Down Expand Up @@ -44,6 +45,13 @@
options.currentAccount = null;
options.store();
}
invoke("check_online_status").then((result) => {
console.debug("online status", result);
}).catch(e => {
alert("You are offline! Please connect to the internet and restart the app.\n If this problem persists, please contact the developer.\n\n (Error: " + e + ")");
console.error(e);
});
</script>

<div class="window">
Expand Down

0 comments on commit 655a5f6

Please sign in to comment.