refactor: do not proxy dev server when using localhost on iOS/Android

This commit is contained in:
Lucas Nogueira 2024-10-03 08:53:40 -03:00
parent 6f3a2b38f0
commit 7c6bb5dfd7
No known key found for this signature in database
GPG Key ID: 7C32FCA95C8C95D7
4 changed files with 32 additions and 43 deletions

View File

@ -103,7 +103,7 @@ impl From<Options> 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)?;
}

View File

@ -6,6 +6,7 @@ use std::{
borrow::Cow,
collections::HashMap,
fmt,
net::Ipv4Addr,
sync::{Arc, Mutex, MutexGuard},
};
@ -332,6 +333,20 @@ impl<R: Runtime> AppManager<R> {
self.config.build.dev_url.as_ref()
}
pub(crate) fn proxy_dev_server_url(&self) -> Option<Url> {
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())

View File

@ -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<R: Runtime> WebviewManager<R> {
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<R: Runtime> WebviewManager<R> {
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();
}

View File

@ -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<R: Runtime>(
window_origin: &str,
web_resource_request_handler: Option<Box<WebResourceRequestHandler>>,
) -> 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<R: Runtime>(
&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<R: Runtime>(
fn get_response<R: Runtime>(
request: Request<Vec<u8>>,
#[allow(unused_variables)] manager: &AppManager<R>,
manager: &AppManager<R>,
window_origin: &str,
web_resource_request_handler: Option<&WebResourceRequestHandler>,
#[cfg(all(dev, mobile))] (url, response_cache): (
&str,
&Arc<Mutex<HashMap<String, CachedResponse>>>,
),
response_cache: &Arc<Mutex<HashMap<String, CachedResponse>>>,
) -> Result<HttpResponse<Cow<'static, [u8]>>, Box<dyn std::error::Error>> {
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<R: Runtime>(
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<R: Runtime>(
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<R: Runtime>(
}
builder.body(asset.bytes.into())?
};
if let Some(handler) = &web_resource_request_handler {
handler(request, &mut response);
}