## Summary - add a server-backed HTTPS proxy flow for Tauri remote windows so self-signed remote HTTPS works with the local CLI TLS assets and desktop auth/cookie handling - manage remote proxy sessions through `packages/server` with per-session bootstrap, local-only cleanup, and explicit session lifecycle handling - support the Tauri desktop flow across environments, including packaged Windows builds, `tauri dev`, and updated Linux/macOS handling for the new local HTTPS proxy path ## Testing - `npm run build --workspace @neuralnomads/codenomad` - `cargo check` - `npm run build --workspace @codenomad/tauri-app` - Windows smoke test for concurrent remote proxy bootstrap sessions - Windows manual validation of packaged Tauri remote connection flow ## Notes - Windows was validated end-to-end. - Linux and macOS code paths were updated for the new proxy flow, but runtime validation on those platforms is still pending. --------- Co-authored-by: Shantur Rathore <i@shantur.com>
89 lines
2.5 KiB
Rust
89 lines
2.5 KiB
Rust
use crate::AppState;
|
|
use tauri::{AppHandle, Manager, WebviewWindow};
|
|
use url::Url;
|
|
use webkit2gtk::{WebContextExt, WebView, WebViewExt};
|
|
|
|
pub fn should_bootstrap_tls_navigation(target_url: &Url, allow_tls_certificate: bool) -> bool {
|
|
allow_tls_certificate && target_url.scheme() == "https"
|
|
}
|
|
|
|
pub fn ensure_remote_window_tls_handler(
|
|
window: &WebviewWindow,
|
|
app_handle: &AppHandle,
|
|
window_label: &str,
|
|
) -> Result<(), String> {
|
|
{
|
|
let state = app_handle.state::<AppState>();
|
|
let mut handlers = state
|
|
.remote_tls_handlers
|
|
.lock()
|
|
.map_err(|err| err.to_string())?;
|
|
if !handlers.insert(window_label.to_string()) {
|
|
return Ok(());
|
|
}
|
|
}
|
|
|
|
let app_handle = app_handle.clone();
|
|
let window_label = window_label.to_string();
|
|
window
|
|
.with_webview(move |platform_webview| {
|
|
let webview = platform_webview.inner();
|
|
let app_handle = app_handle.clone();
|
|
let window_label = window_label.clone();
|
|
webview.connect_load_failed_with_tls_errors(move |view, failing_uri, certificate, _| {
|
|
allow_remote_tls_certificate(
|
|
&app_handle,
|
|
&window_label,
|
|
view,
|
|
failing_uri,
|
|
certificate,
|
|
)
|
|
});
|
|
})
|
|
.map_err(|err| err.to_string())
|
|
}
|
|
|
|
fn allow_remote_tls_certificate(
|
|
app_handle: &AppHandle,
|
|
window_label: &str,
|
|
view: &WebView,
|
|
failing_uri: &str,
|
|
certificate: &webkit2gtk::gio::TlsCertificate,
|
|
) -> bool {
|
|
let Ok(parsed_uri) = Url::parse(failing_uri) else {
|
|
return false;
|
|
};
|
|
let Some(host) = parsed_uri.host_str() else {
|
|
return false;
|
|
};
|
|
|
|
let state = app_handle.state::<AppState>();
|
|
let skip_tls_verify = state
|
|
.remote_skip_tls_verify
|
|
.lock()
|
|
.ok()
|
|
.and_then(|values| values.get(window_label).copied())
|
|
.unwrap_or(false);
|
|
if !skip_tls_verify {
|
|
return false;
|
|
}
|
|
|
|
let expected_origin = state
|
|
.remote_origins
|
|
.lock()
|
|
.ok()
|
|
.and_then(|origins| origins.get(window_label).cloned());
|
|
let parsed_origin = parsed_uri.origin().ascii_serialization();
|
|
if expected_origin.as_deref() != Some(parsed_origin.as_str()) {
|
|
return false;
|
|
}
|
|
|
|
let Some(context) = view.context() else {
|
|
return false;
|
|
};
|
|
|
|
context.allow_tls_certificate_for_host(certificate, host);
|
|
view.load_uri(failing_uri);
|
|
true
|
|
}
|