feat(cli): allow using iOS device tun address for dev server (#10456)

- Changes the IP prompt to also show IPV6 address ending with ::2 (usually device's address)
- Adds --host option on ios dev to force the host
- Also makes it work with our own dev server impl (builtin)
This commit is contained in:
Lucas Fernandes Nogueira
2024-08-02 10:04:08 -03:00
committed by GitHub
parent 7ba67b4aca
commit 786f188923
8 changed files with 69 additions and 86 deletions

View File

@@ -11,8 +11,7 @@
},
"dependencies": {
"@tauri-apps/api": "../../tooling/api/dist",
"@zerodevx/svelte-json-view": "1.0.9",
"internal-ip": "^7.0.0"
"@zerodevx/svelte-json-view": "1.0.9"
},
"devDependencies": {
"@iconify-json/codicon": "^1.1.49",

View File

@@ -5,7 +5,6 @@
import { defineConfig } from 'vite'
import Unocss from 'unocss/vite'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { internalIpV4Sync } from 'internal-ip'
const host = process.env.TAURI_DEV_HOST
@@ -27,13 +26,13 @@ export default defineConfig({
clearScreen: false,
// tauri expects a fixed port, fail if that port is not available
server: {
host: host ? '0.0.0.0' : false,
host: host || false,
port: 1420,
strictPort: true,
hmr: host
? {
protocol: 'ws',
host: internalIpV4Sync(),
host: host,
port: 1430
}
: undefined,

View File

@@ -1015,13 +1015,6 @@ deepmerge@^4.3.1:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
default-gateway@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==
dependencies:
execa "^5.0.0"
defu@^6.1.4:
version "6.1.4"
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
@@ -1098,7 +1091,7 @@ estree-walker@^3.0.0, estree-walker@^3.0.3:
dependencies:
"@types/estree" "^1.0.0"
execa@^5.0.0, execa@^5.1.1:
execa@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
@@ -1190,26 +1183,6 @@ human-signals@^2.1.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
internal-ip@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-7.0.0.tgz#5b1c6a9d7e188aa73a1b69717daf50c8d8ed774f"
integrity sha512-qE4TeD4brqC45Vq/+VASeMiS1KRyfBkR6HT2sh9pZVVCzSjPkaCEfKFU+dL0PRv7NHJtvoKN2r82G6wTfzorkw==
dependencies:
default-gateway "^6.0.3"
ipaddr.js "^2.0.1"
is-ip "^3.1.0"
p-event "^4.2.0"
ip-regex@^4.0.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5"
integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
ipaddr.js@^2.0.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8"
integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==
is-binary-path@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
@@ -1229,13 +1202,6 @@ is-glob@^4.0.1, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
is-ip@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8"
integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==
dependencies:
ip-regex "^4.0.0"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
@@ -1413,18 +1379,6 @@ onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"
p-event@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5"
integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==
dependencies:
p-timeout "^3.1.0"
p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
@@ -1439,13 +1393,6 @@ p-locate@^5.0.0:
dependencies:
p-limit "^3.0.2"
p-timeout@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe"
integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==
dependencies:
p-finally "^1.0.0"
path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"

View File

@@ -21,7 +21,7 @@ use tauri_utils::platform::Target;
use std::{
env::set_current_dir,
net::Ipv4Addr,
net::{IpAddr, Ipv4Addr},
process::{exit, Command, Stdio},
sync::{
atomic::{AtomicBool, Ordering},
@@ -82,6 +82,9 @@ pub struct Options {
/// Specify port for the built-in dev server for static files. Defaults to 1430.
#[clap(long, env = "TAURI_CLI_PORT")]
pub port: Option<u16>,
#[clap(skip)]
pub host: Option<IpAddr>,
}
pub fn command(options: Options) -> Result<()> {
@@ -249,8 +252,11 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
if path.exists() {
let path = path.canonicalize()?;
let server_url =
builtin_dev_server::start(path, Ipv4Addr::new(127, 0, 0, 1).into(), options.port)?;
let ip = options
.host
.unwrap_or_else(|| Ipv4Addr::new(127, 0, 0, 1).into());
let server_url = builtin_dev_server::start(path, ip, options.port)?;
let server_url = format!("http://{server_url}");
dev_url = Some(server_url.parse().unwrap());

View File

@@ -86,6 +86,7 @@ impl From<Options> for DevOptions {
no_dev_server: options.no_dev_server,
port: options.port,
release_mode: options.release_mode,
host: None,
}
}
}

View File

@@ -32,7 +32,7 @@ use cargo_mobile2::{
use std::{
env::set_current_dir,
net::{IpAddr, Ipv4Addr},
net::{IpAddr, Ipv4Addr, SocketAddr},
sync::OnceLock,
};
@@ -76,6 +76,7 @@ pub struct Options {
#[clap(long)]
pub force_ip_prompt: bool,
/// Use the public network address for the development server.
/// If an actual address it provided, it is used instead of prompting to pick one.
///
/// This option is particularly useful along the `--open` flag when you intend on running on a physical device.
///
@@ -87,7 +88,7 @@ pub struct Options {
/// environment variable so you can check this on your framework's configuration to expose the development server
/// on the public network address.
#[clap(long)]
pub host: bool,
pub host: Option<Option<IpAddr>>,
/// Disable the built-in dev server for static files.
#[clap(long)]
pub no_dev_server: bool,
@@ -110,6 +111,7 @@ impl From<Options> for DevOptions {
no_dev_server: options.no_dev_server,
no_dev_server_wait: options.no_dev_server_wait,
port: options.port,
host: None,
}
}
}
@@ -204,7 +206,8 @@ fn local_ip_address(force: bool) -> &'static IpAddr {
.map(|(_, ipaddr)| ipaddr)
.filter(|ipaddr| match ipaddr {
IpAddr::V4(i) => i != &Ipv4Addr::LOCALHOST,
_ => false,
IpAddr::V6(i) => i.to_string().ends_with("::2"),
})
.collect();
match addresses.len() {
@@ -239,8 +242,8 @@ fn local_ip_address(force: bool) -> &'static IpAddr {
fn use_network_address_for_dev_url(
config: &ConfigHandle,
config_extension: &mut Option<ConfigValue>,
force_ip_prompt: bool,
options: &mut Options,
dev_options: &mut DevOptions,
) -> crate::Result<()> {
let mut dev_url = config
.lock()
@@ -251,7 +254,7 @@ fn use_network_address_for_dev_url(
.dev_url
.clone();
if let Some(url) = &mut dev_url {
let ip = if let Some(url) = &mut dev_url {
let localhost = match url.host() {
Some(url::Host::Domain(d)) => d == "localhost",
Some(url::Host::Ipv4(i)) => {
@@ -261,15 +264,23 @@ fn use_network_address_for_dev_url(
};
if localhost {
let ip = local_ip_address(force_ip_prompt).to_string();
println!(
"Replacing devUrl host with {ip}. {}. {}.",
"If your frontend is not listening on that address, try configuring your development server to use 0.0.0.0 as host",
"When this is required, Tauri sets the TAURI_DEV_HOST environment variable"
let ip = options
.host
.unwrap_or_default()
.unwrap_or_else(|| *local_ip_address(options.force_ip_prompt));
log::info!(
"Replacing devUrl host with {ip}. {}.",
"If your frontend is not listening on that address, try configuring your development server to use the `TAURI_DEV_HOST` environment variable or 0.0.0.0 as host"
);
url.set_host(Some(&ip)).unwrap();
if let Some(c) = config_extension {
*url = url::Url::parse(&format!(
"{}://{}{}",
url.scheme(),
SocketAddr::new(ip, url.port_or_known_default().unwrap()),
url.path()
))?;
if let Some(c) = &mut options.config {
if let Some(build) = c
.0
.as_object_mut()
@@ -282,11 +293,34 @@ fn use_network_address_for_dev_url(
let mut build = serde_json::Map::new();
build.insert("devUrl".into(), url.to_string().into());
config_extension.replace(crate::ConfigValue(serde_json::json!({
"build": build
})));
options
.config
.replace(crate::ConfigValue(serde_json::json!({
"build": build
})));
}
reload_config(config_extension.as_ref().map(|c| &c.0))?;
reload_config(options.config.as_ref().map(|c| &c.0))?;
Some(ip)
} else {
None
}
} else if !dev_options.no_dev_server {
let ip = options
.host
.unwrap_or_default()
.unwrap_or_else(|| *local_ip_address(options.force_ip_prompt));
dev_options.host.replace(ip.clone());
Some(ip)
} else {
None
};
if let Some(ip) = ip {
std::env::set_var("TAURI_DEV_HOST", ip.to_string());
if ip.is_ipv6() {
// in this case we can't ping the server for some reason
dev_options.no_dev_server_wait = true;
}
}
@@ -306,14 +340,13 @@ fn run_dev(
noise_level: NoiseLevel,
) -> Result<()> {
// when running on an actual device we must use the network IP
if options.host
if options.host.is_some()
|| device
.as_ref()
.map(|device| !matches!(device.kind(), DeviceKind::Simulator))
.unwrap_or(false)
{
std::env::set_var("TAURI_DEV_HOST", "true");
use_network_address_for_dev_url(&tauri_config, &mut options.config, options.force_ip_prompt)?;
use_network_address_for_dev_url(&tauri_config, &mut options, &mut dev_options)?;
}
crate::dev::setup(&interface, &mut dev_options, tauri_config.clone())?;

View File

@@ -15,7 +15,6 @@
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.1",
"internal-ip": "^7.0.0",
"svelte": "^3.49.0",
"vite": "^3.0.2",
"@tauri-apps/cli": "^2.0.0-alpha.17"

View File

@@ -1,6 +1,5 @@
import { defineConfig } from "vite";
import { svelte } from "@sveltejs/vite-plugin-svelte";
import { internalIpV4Sync } from 'internal-ip';
const host = process.env.TAURI_DEV_HOST;
@@ -13,12 +12,12 @@ export default defineConfig({
clearScreen: false,
// tauri expects a fixed port, fail if that port is not available
server: {
host: host ? "0.0.0.0" : false,
host: host || false,
port: 1420,
strictPort: true,
hmr: host ? {
protocol: 'ws',
host: internalIpV4Sync(),
host,
port: 1421
} : undefined,
},