From 7c6bb5dfd7ef7a252186c0420ed5978594dd554f Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Thu, 3 Oct 2024 08:53:40 -0300 Subject: [PATCH] refactor: do not proxy dev server when using localhost on iOS/Android --- crates/tauri-cli/src/mobile/android/dev.rs | 9 ++--- crates/tauri/src/manager/mod.rs | 15 +++++++++ crates/tauri/src/manager/webview.rs | 12 +++---- crates/tauri/src/protocol/tauri.rs | 39 ++++++---------------- 4 files changed, 32 insertions(+), 43 deletions(-) diff --git a/crates/tauri-cli/src/mobile/android/dev.rs b/crates/tauri-cli/src/mobile/android/dev.rs index 1a56d737a..292419ed3 100644 --- a/crates/tauri-cli/src/mobile/android/dev.rs +++ b/crates/tauri-cli/src/mobile/android/dev.rs @@ -103,7 +103,7 @@ impl From for DevOptions { no_dev_server: options.no_dev_server, port: options.port, release_mode: options.release_mode, - host: None, + host: options.host.unwrap_or_default(), } } } @@ -197,12 +197,7 @@ fn run_dev( noise_level: NoiseLevel, ) -> Result<()> { // when running on an actual device we must use the network IP - if options.host.is_some() - || device - .as_ref() - .map(|device| !device.serial_no().starts_with("emulator")) - .unwrap_or(false) - { + if options.host.is_some() { use_network_address_for_dev_url(&tauri_config, &mut dev_options, options.force_ip_prompt)?; } diff --git a/crates/tauri/src/manager/mod.rs b/crates/tauri/src/manager/mod.rs index 00b13fef1..442a10b12 100644 --- a/crates/tauri/src/manager/mod.rs +++ b/crates/tauri/src/manager/mod.rs @@ -6,6 +6,7 @@ use std::{ borrow::Cow, collections::HashMap, fmt, + net::Ipv4Addr, sync::{Arc, Mutex, MutexGuard}, }; @@ -332,6 +333,20 @@ impl AppManager { self.config.build.dev_url.as_ref() } + pub(crate) fn proxy_dev_server_url(&self) -> Option { + let proxy = cfg!(mobile) + && cfg!(dev) + && self.config.build.dev_url.as_ref().map_or(false, |url| { + url.host().map_or(false, |host| match host { + url::Host::Domain(d) => d != "localhost", + url::Host::Ipv4(ip) => ip != Ipv4Addr::LOCALHOST, + _ => false, + }) + }); + + proxy.then(|| self.get_url().into_owned()) + } + pub(crate) fn protocol_url(&self) -> Cow<'_, Url> { if cfg!(windows) || cfg!(target_os = "android") { Cow::Owned(Url::parse("http://tauri.localhost").unwrap()) diff --git a/crates/tauri/src/manager/webview.rs b/crates/tauri/src/manager/webview.rs index f625d9294..753f9a749 100644 --- a/crates/tauri/src/manager/webview.rs +++ b/crates/tauri/src/manager/webview.rs @@ -34,12 +34,6 @@ use super::{ AppManager, }; -// we need to proxy the dev server on mobile because we can't use `localhost`, so we use the local IP address -// and we do not get a secure context without the custom protocol that proxies to the dev server -// additionally, we need the custom protocol to inject the initialization scripts on Android -// must also keep in sync with the `let mut response` assignment in prepare_uri_scheme_protocol -pub(crate) const PROXY_DEV_SERVER: bool = cfg!(all(dev, mobile)); - pub(crate) const PROCESS_IPC_MESSAGE_FN: &str = include_str!("../../scripts/process-ipc-message-fn.js"); @@ -403,10 +397,12 @@ impl WebviewManager { let app_manager = manager.manager(); + let proxy_dev_server = app_manager.proxy_dev_server_url().is_some(); + #[allow(unused_mut)] // mut url only for the data-url parsing let mut url = match &pending.webview_attributes.url { WebviewUrl::App(path) => { - let url = if PROXY_DEV_SERVER { + let url = if proxy_dev_server { Cow::Owned(Url::parse("tauri://localhost").unwrap()) } else { app_manager.get_url() @@ -426,7 +422,7 @@ impl WebviewManager { let config_url = app_manager.get_url(); let is_local = config_url.make_relative(url).is_some(); let mut url = url.clone(); - if is_local && PROXY_DEV_SERVER { + if is_local && proxy_dev_server { url.set_scheme("tauri").unwrap(); url.set_host(Some("localhost")).unwrap(); } diff --git a/crates/tauri/src/protocol/tauri.rs b/crates/tauri/src/protocol/tauri.rs index a845d453a..06db5ffe7 100644 --- a/crates/tauri/src/protocol/tauri.rs +++ b/crates/tauri/src/protocol/tauri.rs @@ -7,15 +7,13 @@ use std::{borrow::Cow, sync::Arc}; use http::{header::CONTENT_TYPE, Request, Response as HttpResponse, StatusCode}; use crate::{ - manager::{webview::PROXY_DEV_SERVER, AppManager}, + manager::AppManager, webview::{UriSchemeProtocolHandler, WebResourceRequestHandler}, Runtime, }; -#[cfg(all(dev, mobile))] use std::{collections::HashMap, sync::Mutex}; -#[cfg(all(dev, mobile))] #[derive(Clone)] struct CachedResponse { status: http::StatusCode, @@ -28,18 +26,8 @@ pub fn get( window_origin: &str, web_resource_request_handler: Option>, ) -> UriSchemeProtocolHandler { - #[cfg(all(dev, mobile))] - let url = { - let mut url = manager.get_url().as_str().to_string(); - if url.ends_with('/') { - url.pop(); - } - url - }; - let window_origin = window_origin.to_string(); - #[cfg(all(dev, mobile))] let response_cache = Arc::new(Mutex::new(HashMap::new())); Box::new(move |request, responder| { @@ -48,8 +36,7 @@ pub fn get( &manager, &window_origin, web_resource_request_handler.as_deref(), - #[cfg(all(dev, mobile))] - (&url, &response_cache), + &response_cache, ) { Ok(response) => responder.respond(response), Err(e) => responder.respond( @@ -66,16 +53,15 @@ pub fn get( fn get_response( request: Request>, - #[allow(unused_variables)] manager: &AppManager, + manager: &AppManager, window_origin: &str, web_resource_request_handler: Option<&WebResourceRequestHandler>, - #[cfg(all(dev, mobile))] (url, response_cache): ( - &str, - &Arc>>, - ), + response_cache: &Arc>>, ) -> Result>, Box> { + let proxy_dev_server_url = manager.proxy_dev_server_url(); + // use the entire URI as we are going to proxy the request - let path = if PROXY_DEV_SERVER { + let path = if proxy_dev_server_url.is_some() { request.uri().to_string() } else { // ignore query string and fragment @@ -97,14 +83,13 @@ fn get_response( let mut builder = HttpResponse::builder().header("Access-Control-Allow-Origin", window_origin); - #[cfg(all(dev, mobile))] - let mut response = { + let mut response = if let Some(proxy_dev_server_url) = proxy_dev_server_url { let decoded_path = percent_encoding::percent_decode(path.as_bytes()) .decode_utf8_lossy() .to_string(); let url = format!( "{}/{}", - url.trim_end_matches('/'), + proxy_dev_server_url.as_str().trim_end_matches('/'), decoded_path.trim_start_matches('/') ); @@ -148,10 +133,7 @@ fn get_response( return Err(Box::new(e)); } } - }; - - #[cfg(not(all(dev, mobile)))] - let mut response = { + } else { let asset = manager.get_asset(path)?; builder = builder.header(CONTENT_TYPE, &asset.mime_type); if let Some(csp) = &asset.csp_header { @@ -159,6 +141,7 @@ fn get_response( } builder.body(asset.bytes.into())? }; + if let Some(handler) = &web_resource_request_handler { handler(request, &mut response); }