From b9df197534f9dd61733cbeb93cfe17a50f4fa44c Mon Sep 17 00:00:00 2001 From: quexeky Date: Sun, 9 Feb 2025 21:25:09 +1100 Subject: [PATCH] feat(cache): Caching objects which use the useObject tauri command --- src-tauri/src/lib.rs | 34 ++---------- src-tauri/src/remote/cache.rs | 99 ++++++++++++++++++++++++++++++++--- 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index b29544b..d7c54e8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -41,10 +41,12 @@ use log4rs::Config; use process::commands::{kill_game, launch_game}; use process::process_manager::ProcessManager; use remote::auth::{self, generate_authorization_header, recieve_handshake}; +use remote::cache::{cache_object, fetch_object, fetch_object_offline, get_cached_object, ObjectCache}; use remote::commands::{ auth_initiate, fetch_drop_object, gen_drop_url, manual_recieve_handshake, retry_connect, sign_out, use_remote }; use remote::requests::make_request; +use reqwest::blocking::Body; use serde::{Deserialize, Serialize}; use std::env; use std::path::Path; @@ -358,35 +360,9 @@ pub fn run() { Ok(()) }) - .register_asynchronous_uri_scheme_protocol("object", move |_ctx, request, responder| { - // Drop leading / - let object_id = &request.uri().path()[1..]; - - let header = generate_authorization_header(); - let client: reqwest::blocking::Client = reqwest::blocking::Client::new(); - let response = make_request(&client, &["/api/v1/client/object/", object_id], &[], |f| { - f.header("Authorization", header) - }) - .unwrap() - .send(); - if response.is_err() { - warn!( - "failed to fetch object with error: {}", - response.err().unwrap() - ); - responder.respond(Response::builder().status(500).body(Vec::new()).unwrap()); - return; - } - let response = response.unwrap(); - - let resp_builder = ResponseBuilder::new().header( - CONTENT_TYPE, - response.headers().get("Content-Type").unwrap(), - ); - let data = Vec::from(response.bytes().unwrap()); - let resp = resp_builder.body(data).unwrap(); - - responder.respond(resp); + .register_asynchronous_uri_scheme_protocol("object", move |ctx, request, responder| { + let state: tauri::State<'_, Mutex> = ctx.app_handle().state(); + offline!(state, fetch_object, fetch_object_offline, request, responder); }) .on_window_event(|window, event| { if let WindowEvent::CloseRequested { api, .. } = event { diff --git a/src-tauri/src/remote/cache.rs b/src-tauri/src/remote/cache.rs index db8225d..6be24e9 100644 --- a/src-tauri/src/remote/cache.rs +++ b/src-tauri/src/remote/cache.rs @@ -1,8 +1,10 @@ -use cacache::Integrity; -use serde::{de::DeserializeOwned, Serialize}; - use crate::{database::db::borrow_db_checked, error::remote_access_error::RemoteAccessError}; +use cacache::Integrity; +use http::{header::CONTENT_TYPE, response::Builder as ResponseBuilder, Response}; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use tauri::{UriSchemeContext, UriSchemeResponder}; +use super::{auth::generate_authorization_header, requests::make_request}; #[macro_export] macro_rules! offline { @@ -16,12 +18,93 @@ macro_rules! offline { } } -pub fn cache_object<'a, K: AsRef, D: Serialize + DeserializeOwned>(key: K, data: &D) -> Result { +pub fn cache_object<'a, K: AsRef, D: Serialize + DeserializeOwned>( + key: K, + data: &D, +) -> Result { let bytes = serde_json::to_vec(data).unwrap(); - cacache::write_sync(&borrow_db_checked().cache_dir, key, bytes).map_err(|e| RemoteAccessError::Cache(e)) + cacache::write_sync(&borrow_db_checked().cache_dir, key, bytes) + .map_err(|e| RemoteAccessError::Cache(e)) } -pub fn get_cached_object<'a, K: AsRef, D: Serialize + DeserializeOwned>(key: K) -> Result { - let bytes = cacache::read_sync(&borrow_db_checked().cache_dir, key).map_err(|e| RemoteAccessError::Cache(e))?; +pub fn get_cached_object<'a, K: AsRef, D: Serialize + DeserializeOwned>( + key: K, +) -> Result { + let bytes = cacache::read_sync(&borrow_db_checked().cache_dir, key) + .map_err(|e| RemoteAccessError::Cache(e))?; let data = serde_json::from_slice::(&bytes).unwrap(); Ok(data) -} \ No newline at end of file +} + +pub fn fetch_object( + request: http::Request>, + responder: UriSchemeResponder, +) { + // Drop leading / + let object_id = &request.uri().path()[1..]; + + let header = generate_authorization_header(); + let client: reqwest::blocking::Client = reqwest::blocking::Client::new(); + let response = make_request(&client, &["/api/v1/client/object/", object_id], &[], |f| { + f.header("Authorization", header) + }) + .unwrap() + .send(); + if response.is_err() { + let data = get_cached_object::<&str, ObjectCache>(object_id); + + match data { + Ok(data) => responder.respond(data.into()), + Err(_) => todo!(), + } + return; + } + let response = response.unwrap(); + + let resp_builder = ResponseBuilder::new().header( + CONTENT_TYPE, + response.headers().get("Content-Type").unwrap(), + ); + let data = Vec::from(response.bytes().unwrap()); + let resp = resp_builder.body(data).unwrap(); + cache_object::<&str, ObjectCache>(object_id, &resp.clone().into()).unwrap(); + + responder.respond(resp); +} +pub fn fetch_object_offline( + request: http::Request>, + responder: UriSchemeResponder, +) { + let object_id = &request.uri().path()[1..]; + let data = get_cached_object::<&str, ObjectCache>(object_id); + + match data { + Ok(data) => responder.respond(data.into()), + Err(_) => todo!(), + } +} +#[derive(Serialize, Deserialize)] +pub struct ObjectCache { + content_type: String, + body: Vec, +} + +impl From>> for ObjectCache { + fn from(value: Response>) -> Self { + ObjectCache { + content_type: value + .headers() + .get(CONTENT_TYPE) + .unwrap() + .to_str() + .unwrap() + .to_owned(), + body: value.body().clone(), + } + } +} +impl From for Response> { + fn from(value: ObjectCache) -> Self { + let resp_builder = ResponseBuilder::new().header(CONTENT_TYPE, value.content_type); + resp_builder.body(value.body).unwrap() + } +}