refactor(desktop): move Tauri remote proxy into packages/server

This commit is contained in:
Shantur Rathore
2026-04-19 13:18:30 +01:00
parent d456ae5837
commit d0ddefc168
13 changed files with 1808 additions and 71 deletions

View File

@@ -1,18 +1,13 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
#[cfg_attr(target_os = "linux", allow(dead_code))]
#[allow(dead_code)]
mod cert_manager;
mod cli_manager;
#[cfg(target_os = "linux")]
mod linux_tls;
#[cfg_attr(target_os = "linux", allow(dead_code))]
mod remote_proxy;
use cli_manager::{CliProcessManager, CliStatus};
use keepawake::KeepAwake;
#[cfg(not(target_os = "linux"))]
use remote_proxy::start_remote_proxy;
use remote_proxy::{ProxyTlsConfig, RemoteProxyHandle};
use serde::Deserialize;
use serde_json::json;
use std::collections::{HashMap, HashSet};
@@ -56,7 +51,6 @@ pub struct AppState {
pub remote_origins: Mutex<HashMap<String, String>>,
pub remote_skip_tls_verify: Mutex<HashMap<String, bool>>,
pub remote_tls_handlers: Mutex<HashSet<String>>,
pub remote_proxies: Mutex<HashMap<String, RemoteProxyHandle>>,
}
#[derive(Debug, Deserialize)]
@@ -65,6 +59,8 @@ struct RemoteWindowPayload {
id: String,
name: String,
base_url: String,
entry_url: Option<String>,
#[allow(dead_code)]
skip_tls_verify: bool,
}
@@ -182,49 +178,21 @@ fn intercept_navigation<R: Runtime>(webview: &Webview<R>, url: &Url) -> bool {
async fn open_remote_window_impl(
app: AppHandle,
payload: RemoteWindowPayload,
_tls_config: Option<ProxyTlsConfig>,
) -> Result<(), String> {
let parsed = Url::parse(&payload.base_url).map_err(|err| err.to_string())?;
let entry_url = payload.entry_url.as_deref().unwrap_or(payload.base_url.as_str());
let parsed = Url::parse(entry_url).map_err(|err| err.to_string())?;
let label = format!("remote-{}", payload.id);
let title = format!(
"{} - {}",
payload.name,
parsed.host_str().unwrap_or(payload.base_url.as_str())
Url::parse(&payload.base_url)
.ok()
.and_then(|url| url.host_str().map(str::to_string))
.unwrap_or_else(|| payload.base_url.clone())
);
#[cfg(target_os = "linux")]
let window_url = parsed.clone();
#[cfg(not(target_os = "linux"))]
let window_url = {
let state = app.state::<AppState>();
let reuses_existing_proxy = {
let proxies = state.remote_proxies.lock().map_err(|err| err.to_string())?;
proxies
.get(&label)
.map(|existing| existing.matches(&parsed, payload.skip_tls_verify))
.unwrap_or(false)
};
if reuses_existing_proxy {
let proxies = state.remote_proxies.lock().map_err(|err| err.to_string())?;
proxies
.get(&label)
.map(|handle| handle.entry_url().clone())
.ok_or_else(|| "Remote proxy disappeared before reuse".to_string())?
} else {
let new_proxy =
start_remote_proxy(parsed.clone(), payload.skip_tls_verify, _tls_config).await?;
let local_url = new_proxy.entry_url().clone();
let mut proxies = state.remote_proxies.lock().map_err(|err| err.to_string())?;
if let Some(existing) = proxies.remove(&label) {
existing.shutdown();
}
proxies.insert(label.clone(), new_proxy);
local_url
}
};
app.state::<AppState>()
.remote_origins
.lock()
@@ -234,7 +202,7 @@ async fn open_remote_window_impl(
.remote_skip_tls_verify
.lock()
.map_err(|err| err.to_string())?
.insert(label.clone(), payload.skip_tls_verify);
.insert(label.clone(), parsed.scheme() == "https");
if let Some(existing) = app.get_webview_window(&label) {
#[cfg(target_os = "linux")]
@@ -287,11 +255,6 @@ async fn open_remote_window_impl(
if let Ok(mut handlers) = app_handle.state::<AppState>().remote_tls_handlers.lock() {
handlers.remove(&label_for_cleanup);
}
if let Ok(mut proxies) = app_handle.state::<AppState>().remote_proxies.lock() {
if let Some(handle) = proxies.remove(&label_for_cleanup) {
handle.shutdown();
}
}
}
});
@@ -300,33 +263,25 @@ async fn open_remote_window_impl(
#[tauri::command]
async fn open_remote_window(app: AppHandle, payload: RemoteWindowPayload) -> Result<(), String> {
#[cfg(target_os = "linux")]
{
return open_remote_window_impl(app, payload, None).await;
}
#[cfg(not(target_os = "linux"))]
let tls_config = match cert_manager::ensure_local_cert() {
Ok(local_cert) => {
{
let entry_url = payload.entry_url.as_deref().unwrap_or(payload.base_url.as_str());
let parsed = Url::parse(entry_url).map_err(|err| err.to_string())?;
if parsed.scheme() == "https" {
let local_cert = cert_manager::ensure_local_cert().map_err(|err| {
format!(
"Failed to load the local HTTPS certificate for the remote proxy window: {err}"
)
})?;
if let Err(err) = cert_manager::trust_cert_in_store(&local_cert.ca_cert_der) {
return Err(format!(
"Failed to trust the local CodeNomad CA certificate. Accept the certificate installation prompt and try again: {err}"
));
}
Some(ProxyTlsConfig {
cert_pem: local_cert.cert_pem,
key_pem: local_cert.key_pem,
})
}
Err(err) => {
return Err(format!(
"Failed to create the local HTTPS proxy certificate. This remote HTTPS connection cannot fall back to HTTP because secure cookies would break: {err}"
));
}
};
}
#[cfg(not(target_os = "linux"))]
open_remote_window_impl(app, payload, tls_config).await
open_remote_window_impl(app, payload).await
}
fn collect_directory_paths(paths: &[std::path::PathBuf]) -> Vec<String> {
@@ -487,7 +442,6 @@ fn main() {
remote_origins: Mutex::new(HashMap::new()),
remote_skip_tls_verify: Mutex::new(HashMap::new()),
remote_tls_handlers: Mutex::new(HashSet::new()),
remote_proxies: Mutex::new(HashMap::new()),
})
.setup(|app| {
set_windows_app_user_model_id();