chore: Remove unwraps from fetch_object and server_proto

Signed-off-by: quexeky <git@quexeky.dev>
This commit is contained in:
quexeky
2025-09-09 09:58:59 +10:00
parent be5500d29f
commit ddde547c08
9 changed files with 85 additions and 48 deletions

View File

@ -21,6 +21,7 @@ use crate::process::commands::open_process_logs;
use crate::process::process_handlers::UMU_LAUNCHER_EXECUTABLE; use crate::process::process_handlers::UMU_LAUNCHER_EXECUTABLE;
use crate::remote::commands::auth_initiate_code; use crate::remote::commands::auth_initiate_code;
use crate::remote::fetch_object::fetch_object_wrapper; use crate::remote::fetch_object::fetch_object_wrapper;
use crate::remote::server_proto::handle_server_proto_wrapper;
use crate::{database::db::DatabaseImpls, games::downloads::commands::resume_download}; use crate::{database::db::DatabaseImpls, games::downloads::commands::resume_download};
use bitcode::{Decode, Encode}; use bitcode::{Decode, Encode};
use client::commands::fetch_state; use client::commands::fetch_state;
@ -61,7 +62,7 @@ use remote::commands::{
auth_initiate, fetch_drop_object, gen_drop_url, manual_recieve_handshake, retry_connect, auth_initiate, fetch_drop_object, gen_drop_url, manual_recieve_handshake, retry_connect,
sign_out, use_remote, sign_out, use_remote,
}; };
use remote::server_proto::{handle_server_proto, handle_server_proto_offline}; use remote::server_proto::handle_server_proto_offline_wrapper;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fs::File; use std::fs::File;
use std::io::Write; use std::io::Write;
@ -473,8 +474,8 @@ pub fn run() {
offline!( offline!(
state, state,
handle_server_proto, handle_server_proto_wrapper,
handle_server_proto_offline, handle_server_proto_offline_wrapper,
request, request,
responder responder
) )

View File

@ -9,7 +9,7 @@ use tauri::{AppHandle, Emitter, Manager};
use url::Url; use url::Url;
use crate::{ use crate::{
database::{ app_emit, database::{
db::{borrow_db_checked, borrow_db_mut_checked}, db::{borrow_db_checked, borrow_db_mut_checked},
models::data::DatabaseAuth, models::data::DatabaseAuth,
}, error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}, remote::{requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}}, AppState, AppStatus, User }, error::{drop_server_error::DropServerError, remote_access_error::RemoteAccessError}, remote::{requests::make_authenticated_get, utils::{DROP_CLIENT_ASYNC, DROP_CLIENT_SYNC}}, AppState, AppStatus, User
@ -83,7 +83,7 @@ pub async fn fetch_user() -> Result<User, RemoteAccessError> {
async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAccessError> { async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), RemoteAccessError> {
let path_chunks: Vec<&str> = path.split('/').collect(); let path_chunks: Vec<&str> = path.split('/').collect();
if path_chunks.len() != 3 { if path_chunks.len() != 3 {
app.emit("auth/failed", ()).unwrap(); app_emit!(app, "auth/failed", ());
return Err(RemoteAccessError::HandshakeFailed( return Err(RemoteAccessError::HandshakeFailed(
"failed to parse token".to_string(), "failed to parse token".to_string(),
)); ));
@ -141,12 +141,12 @@ async fn recieve_handshake_logic(app: &AppHandle, path: String) -> Result<(), Re
pub async fn recieve_handshake(app: AppHandle, path: String) { pub async fn recieve_handshake(app: AppHandle, path: String) {
// Tell the app we're processing // Tell the app we're processing
app.emit("auth/processing", ()).unwrap(); app_emit!(app, "auth/processing", ());
let handshake_result = recieve_handshake_logic(&app, path).await; let handshake_result = recieve_handshake_logic(&app, path).await;
if let Err(e) = handshake_result { if let Err(e) = handshake_result {
warn!("error with authentication: {e}"); warn!("error with authentication: {e}");
app.emit("auth/failed", e.to_string()).unwrap(); app_emit!(app, "auth/failed", e.to_string());
return; return;
} }
@ -161,7 +161,7 @@ pub async fn recieve_handshake(app: AppHandle, path: String) {
drop(state_lock); drop(state_lock);
app.emit("auth/finished", ()).unwrap(); app_emit!(app, "auth/finished", ());
} }
pub fn auth_initiate_logic(mode: String) -> Result<String, RemoteAccessError> { pub fn auth_initiate_logic(mode: String) -> Result<String, RemoteAccessError> {

View File

@ -10,7 +10,7 @@ use crate::{
error::{cache_error::CacheError, remote_access_error::RemoteAccessError}, error::{cache_error::CacheError, remote_access_error::RemoteAccessError},
}; };
use bitcode::{Decode, DecodeOwned, Encode}; use bitcode::{Decode, DecodeOwned, Encode};
use http::{header::{ToStrError, CONTENT_TYPE}, response::Builder as ResponseBuilder, Response}; use http::{header::{CONTENT_TYPE}, response::Builder as ResponseBuilder, Response};
#[macro_export] #[macro_export]
macro_rules! offline { macro_rules! offline {

View File

@ -8,14 +8,11 @@ use tauri::{AppHandle, Emitter, Manager};
use url::Url; use url::Url;
use crate::{ use crate::{
AppState, AppStatus, app_emit, database::db::{borrow_db_checked, borrow_db_mut_checked}, error::remote_access_error::RemoteAccessError, remote::{
database::db::{borrow_db_checked, borrow_db_mut_checked},
error::remote_access_error::RemoteAccessError,
remote::{
auth::generate_authorization_header, auth::generate_authorization_header,
requests::generate_url, requests::generate_url,
utils::{DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT}, utils::{DROP_CLIENT_SYNC, DROP_CLIENT_WS_CLIENT},
}, }, AppState, AppStatus
}; };
use super::{ use super::{
@ -83,7 +80,7 @@ pub fn sign_out(app: AppHandle) {
} }
// Emit event for frontend // Emit event for frontend
app.emit("auth/signedout", ()).unwrap(); app_emit!(app, "auth/signedout", ());
} }
#[tauri::command] #[tauri::command]
@ -167,7 +164,7 @@ pub fn auth_initiate_code(app: AppHandle) -> Result<String, RemoteAccessError> {
let result = load().await; let result = load().await;
if let Err(err) = result { if let Err(err) = result {
warn!("{err}"); warn!("{err}");
app.emit("auth/failed", err.to_string()).unwrap(); app_emit!(app, "auth/failed", err.to_string());
} }
}); });

View File

@ -13,8 +13,8 @@ pub async fn fetch_object_wrapper(request: http::Request<Vec<u8>>, responder: Ur
match fetch_object(request).await { match fetch_object(request).await {
Ok(r) => responder.respond(r), Ok(r) => responder.respond(r),
Err(e) => { Err(e) => {
warn!("Cache error: {}", e); warn!("Cache error: {e}");
responder.respond(Response::new(Vec::new())); responder.respond(Response::builder().status(500).body(Vec::new()).expect("Failed to build error response"));
} }
}; };
} }
@ -36,7 +36,7 @@ pub async fn fetch_object(request: http::Request<Vec<u8>>) -> Result<Response<Ve
let url = format!("{}api/v1/client/object/{object_id}", DB.fetch_base_url()); let url = format!("{}api/v1/client/object/{object_id}", DB.fetch_base_url());
let response = client.get(url).header("Authorization", header).send().await; let response = client.get(url).header("Authorization", header).send().await;
match response { return match response {
Ok(r) => { Ok(r) => {
let resp_builder = ResponseBuilder::new().header( let resp_builder = ResponseBuilder::new().header(
CONTENT_TYPE, CONTENT_TYPE,
@ -48,8 +48,7 @@ pub async fn fetch_object(request: http::Request<Vec<u8>>) -> Result<Response<Ve
Ok(data) => Vec::from(data), Ok(data) => Vec::from(data),
Err(e) => { Err(e) => {
warn!( warn!(
"Could not get data from cache object {} with error {}", "Could not get data from cache object {object_id} with error {e}",
object_id, e
); );
Vec::new() Vec::new()
} }
@ -60,11 +59,11 @@ pub async fn fetch_object(request: http::Request<Vec<u8>>) -> Result<Response<Ve
.expect("Failed to create cached object"); .expect("Failed to create cached object");
} }
return Ok(resp.into()); Ok(resp.into())
} }
Err(e) => { Err(e) => {
debug!("Object fetch failed with error {}. Attempting to download from cache", e); debug!("Object fetch failed with error {}. Attempting to download from cache", e);
return match cache_result { match cache_result {
Ok(cache_result) => Ok(cache_result.into()), Ok(cache_result) => Ok(cache_result.into()),
Err(e) => { Err(e) => {
warn!("{e}"); warn!("{e}");

View File

@ -1,57 +1,88 @@
use std::str::FromStr; use std::str::FromStr;
use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri}; use http::{uri::PathAndQuery, Request, Response, StatusCode, Uri};
use log::warn;
use tauri::UriSchemeResponder; use tauri::UriSchemeResponder;
use crate::{database::db::borrow_db_checked, remote::utils::DROP_CLIENT_SYNC}; use crate::{database::db::borrow_db_checked, remote::utils::DROP_CLIENT_SYNC};
pub async fn handle_server_proto_offline(_request: Request<Vec<u8>>, responder: UriSchemeResponder) { pub async fn handle_server_proto_offline_wrapper(request: Request<Vec<u8>>, responder: UriSchemeResponder) {
let four_oh_four = Response::builder() responder.respond(match handle_server_proto_offline(request).await {
.status(StatusCode::NOT_FOUND) Ok(res) => res,
.body(Vec::new()) Err(e) => unreachable!()
.unwrap(); });
responder.respond(four_oh_four);
} }
pub async fn handle_server_proto(request: Request<Vec<u8>>, responder: UriSchemeResponder) { pub async fn handle_server_proto_offline(_request: Request<Vec<u8>>) -> Result<Response<Vec<u8>>, StatusCode>{
Ok(Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Vec::new())
.expect("Failed to build error response for proto offline"))
}
pub async fn handle_server_proto_wrapper(request: Request<Vec<u8>>, responder: UriSchemeResponder) {
match handle_server_proto(request).await {
Ok(r) => responder.respond(r),
Err(e) => {
warn!("Cache error: {e}");
responder.respond(Response::builder().status(e).body(Vec::new()).expect("Failed to build error response"));
}
}
}
async fn handle_server_proto(request: Request<Vec<u8>>) -> Result<Response<Vec<u8>>, StatusCode> {
let db_handle = borrow_db_checked(); let db_handle = borrow_db_checked();
let web_token = match &db_handle.auth.as_ref().unwrap().web_token { let web_token = match &db_handle.auth.as_ref().unwrap().web_token {
Some(e) => e, Some(e) => e,
None => return, None => return Err(StatusCode::BAD_REQUEST),
}; };
let remote_uri = db_handle.base_url.parse::<Uri>().unwrap(); let remote_uri = db_handle.base_url.parse::<Uri>().expect("Failed to parse base url");
let path = request.uri().path(); let path = request.uri().path();
let mut new_uri = request.uri().clone().into_parts(); let mut new_uri = request.uri().clone().into_parts();
new_uri.path_and_query = new_uri.path_and_query =
Some(PathAndQuery::from_str(&format!("{path}?noWrapper=true")).unwrap()); Some(PathAndQuery::from_str(&format!("{path}?noWrapper=true")).expect("Failed to parse request path in proto"));
new_uri.authority = remote_uri.authority().cloned(); new_uri.authority = remote_uri.authority().cloned();
new_uri.scheme = remote_uri.scheme().cloned(); new_uri.scheme = remote_uri.scheme().cloned();
let new_uri = Uri::from_parts(new_uri).unwrap(); let new_uri = Uri::from_parts(new_uri).expect(&format!("Failed to build new uri from parts"));
let whitelist_prefix = ["/store", "/api", "/_", "/fonts"]; let whitelist_prefix = ["/store", "/api", "/_", "/fonts"];
if whitelist_prefix.iter().all(|f| !path.starts_with(f)) { if whitelist_prefix.iter().all(|f| !path.starts_with(f)) {
webbrowser::open(&new_uri.to_string()).unwrap(); return match webbrowser::open(&new_uri.to_string()) {
return; Ok(_) => Ok(Response::new(Vec::new())),
Err(e) => {
warn!("Could not open web browser to link {new_uri} with error {e}");
Ok(Response::new(Vec::new()))
}
}
} }
let client = DROP_CLIENT_SYNC.clone(); let client = DROP_CLIENT_SYNC.clone();
let response = client let response = match client
.request(request.method().clone(), new_uri.to_string()) .request(request.method().clone(), new_uri.to_string())
.header("Authorization", format!("Bearer {web_token}")) .header("Authorization", format!("Bearer {web_token}"))
.headers(request.headers().clone()) .headers(request.headers().clone())
.send() .send() {
.unwrap(); Ok(response) => response,
Err(e) => {
warn!("Could not send response. Got {e} when sending");
return Err(e.status().unwrap_or(StatusCode::BAD_REQUEST))
},
};
let response_status = response.status(); let response_status = response.status();
let response_body = response.bytes().unwrap(); let response_body = match response.bytes() {
Ok(bytes) => bytes,
Err(e) => return Err(e.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR)),
};
let http_response = Response::builder() let http_response = Response::builder()
.status(response_status) .status(response_status)
.body(response_body.to_vec()) .body(response_body.to_vec())
.unwrap(); .expect("Failed to build server proto response");
responder.respond(http_response); Ok(http_response)
} }

View File

@ -11,10 +11,7 @@ use serde::Deserialize;
use url::Url; use url::Url;
use crate::{ use crate::{
AppState, AppStatus, database::db::{borrow_db_mut_checked, DATA_ROOT_DIR}, error::remote_access_error::RemoteAccessError, state_lock, AppState, AppStatus
database::db::{DATA_ROOT_DIR, borrow_db_mut_checked},
error::remote_access_error::RemoteAccessError,
state_lock,
}; };
#[derive(Deserialize)] #[derive(Deserialize)]

View File

@ -0,0 +1,11 @@
#[macro_export]
macro_rules! app_emit {
($app:expr, $event:expr, $p:expr) => {
match $app.emit($event, $p) {
Ok(_) => (),
Err(e) => {
log::error!("Failed to emit event {} with error {}", $event, e);
}
};
};
}

View File

@ -1 +1,2 @@
pub mod state_lock; mod app_emit;
mod state_lock;