Repository: tauri-apps/tauri (language: rust)

Issue:
[bug] undeclared hyper-tls dependency of tauri causes failure with offline builds
### Describe the bug

I recently tried to package an application that was build with tauri, but in my build sandbox I encountered the following error:

```
    Info `tauri-build` dependency has workspace inheritance enabled. The features array won't be automatically rewritten. Expected features: []
    Info `tauri` dependency has workspace inheritance enabled. The features array won't be automatically rewritten. Expected features: []
error: no matching package found
searched package name: `hyper-tls`
perhaps you meant:      hyper-rustls or hyper-util
location searched: registry `crates-io`
required by package `reqwest v0.12.8`
    ... which satisfies dependency `reqwest = "^0.12.5"` (locked to 0.12.8) of package `firezone-gui-client-common v1.4.0 (/build/source/rust/gui-client/src-common)`
    ... which satisfies path dependency `firezone-gui-client-common` (locked to 1.4.0) of package `firezone-gui-client v1.4.0 (/build/source/rust/gui-client/src-tauri)`
As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag.
    Error failed to build app:
```

For context, I pre-download all dependencies using `cargo vendor` and later build without network access, but for some reason that is unknown to me, `tauri build` seems to execute a cargo build that requires more than what I have in my lock file. Specifically, it will try to fetch `hyper-tls` which then fails. The obvious and simplest solution for me was to add `hyper-tls` to the project dependencies (either directly or by enabling tauri's `native-tls` feature), even though the project doesn't actually depend on it. This just makes sure the dependency is available in the vendored directory so `tauri build` can succeed.

I also cannot figure out how to remove this dependency, say if I wanted to use `rustls` instead hyper-tls which seems to pull in openssl. Unfortunately, I don't know enough about tauri to find the root cause for this. It does however seem like something that shouldn't be happening.

### Reproduction

```bash
$ git clone https://github.com/firezone/firezone
$ git checkout 8c9427b7b133e5050be34c2ac0e831c12c08f02c
$ cd firezone/rust
$ cargo vendor          # follow instructions by cargo vendor and copy stuff to .cargo/config.toml
$ mkdir gui-client/dist # just a dummy, the error will happen way before we get to frontend stuff
$ cd gui-client
$ cargo tauri build -- --offline

    Info `tauri-build` dependency has workspace inheritance enabled. The features array won't be automatically rewritten. Expected features: []
    Info `tauri` dependency has workspace inheritance enabled. The features array won't be automatically rewritten. Expected features: []
error: no matching package found
searched package name: `hyper-tls`
perhaps you meant:      hyper-rustls or hyper-util
location searched: registry `crates-io`
required by package `reqwest v0.12.9`
    ... which satisfies dependency `reqwest = "^0.12.9"` (locked to 0.12.9) of package `firezone-gui-client-common v1.4.1 (/home/malte/firezone/rust/gui-client/src-common)`
    ... which satisfies path dependency `firezone-gui-client-common` (locked to 1.4.1) of package `firezone-gui-client v1.4.1 (/home/malte/firezone/rust/gui-client/src-tauri)`
As a reminder, you're using offline mode (--offline) which can sometimes cause surprising resolution failures, if this error is too confusing you may wish to retry without the offline flag.
    Error failed to build app:
```

### Expected behavior

All dependencies should be declared.

### Full `tauri info` output

```text
[-] Packages
    - tauri 🦀: 2.2.2
    - tauri-build 🦀: 2.0.5
    - wry 🦀: 0.48.0
    - tao 🦀: 0.31.0
    - tauri-cli 🦀: 2.1.0
    - @tauri-apps/api : not installed!
    - @tauri-apps/cli : 2.1.0

[-] Plugins
    - tauri-plugin-dialog 🦀: 2.2.0
    - @tauri-apps/plugin-dialog : not installed!
    - tauri-plugin-notification 🦀: 2.2.0
    - @tauri-apps/plugin-notification : not installed!
    - tauri-plugin-shell 🦀: 2.2.0
    - @tauri-apps/plugin-shell : not installed!
    - tauri-plugin-fs 🦀: 2.2.0
    - @tauri-apps/plugin-fs : not installed!

[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../dist
    - bundler: Vite
```

### Stack trace

```text
N/A
```

### Additional context

_No response_


Discussion / hints:

Fix patch:
diff --git a/.changes/cli-core-native-tls.md b/.changes/cli-core-native-tls.md
new file mode 100644
index 000000000000..71b12bf0f4dc
--- /dev/null
+++ b/.changes/cli-core-native-tls.md
@@ -0,0 +1,6 @@
+---
+tauri-cli: patch:bug
+tauri: patch:bug
+---
+
+Fixed an issue that caused Tauri's CLI to enable tauri's `native-tls` feature even though it wasn't needed. Moved `reqwest` to a mobile-only dependency in `tauri` and enabled its `rustls-tls` feature flag.
diff --git a/Cargo.lock b/Cargo.lock
index b5adbdfd2af8..dbfdfe428f5c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6937,7 +6937,7 @@ dependencies = [
  "once_cell",
  "socket2",
  "tracing",
- "windows-sys 0.59.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
diff --git a/crates/tauri-cli/src/interface/rust.rs b/crates/tauri-cli/src/interface/rust.rs
index 84fd7b93b70d..b9da54da7b16 100644
--- a/crates/tauri-cli/src/interface/rust.rs
+++ b/crates/tauri-cli/src/interface/rust.rs
@@ -360,35 +360,6 @@ fn lookup<F: FnMut(FileType, PathBuf)>(dir: &Path, mut f: F) {
   }
 }
 
-fn shared_options(
-  desktop_dev: bool,
-  mobile: bool,
-  args: &mut Vec<String>,
-  features: &mut Option<Vec<String>>,
-  app_settings: &RustAppSettings,
-) {
-  if mobile {
-    args.push("--lib".into());
-    features
-      .get_or_insert(Vec::new())
-      .push("tauri/rustls-tls".into());
-  } else {
-    if !desktop_dev {
-      args.push("--bins".into());
-    }
-    let all_features = app_settings
-      .manifest
-      .lock()
-      .unwrap()
-      .all_enabled_features(if let Some(f) = features { f } else { &[] });
-    if !all_features.contains(&"tauri/rustls-tls".into()) {
-      features
-        .get_or_insert(Vec::new())
-        .push("tauri/native-tls".into());
-    }
-  }
-}
-
 fn dev_options(
   mobile: bool,
   args: &mut Vec<String>,
@@ -409,7 +380,11 @@ fn dev_options(
   }
   *args = dev_args;
 
-  shared_options(true, mobile, args, features, app_settings);
+  if mobile {
+    args.push("--lib".into());
+  } else {
+    args.push("--bins".into());
+  }
 
   if !args.contains(&"--no-default-features".into()) {
     let manifest_features = app_settings.manifest.lock().unwrap().features();
@@ -489,7 +464,9 @@ impl Rust {
     features
       .get_or_insert(Vec::new())
       .push("tauri/custom-protocol".into());
-    shared_options(false, mobile, args, features, &self.app_settings);
+    if mobile {
+      args.push("--lib".into());
+    }
   }
 
   fn run_dev<F: Fn(Option<i32>, ExitReason) + Send + Sync + 'static>(
diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml
index 6a9b40ee5fdb..946985c13a51 100644
--- a/crates/tauri/Cargo.toml
+++ b/crates/tauri/Cargo.toml
@@ -68,11 +68,6 @@ serde_repr = "0.1"
 http = "1"
 dirs = "5"
 percent-encoding = "2"
-reqwest = { version = "0.12", default-features = false, features = [
-  "json",
-  "stream",
-] }
-bytes = { version = "1", features = ["serde"] }
 raw-window-handle = { version = "0.6", features = ["std"] }
 glob = "0.3"
 urlpattern = "0.3"
@@ -89,13 +84,16 @@ specta = { version = "^2.0.0-rc.16", optional = true, default-features = false,
   "function",
   "derive",
 ] }
-[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
+
+# desktop
+[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd", target_os = "windows", target_os = "macos"))'.dependencies]
 muda = { version = "0.15", default-features = false, features = ["serde"] }
 tray-icon = { version = "0.19", default-features = false, features = [
   "serde",
 ], optional = true }
 
-[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
+# linux
+[target.'cfg(any(target_os = "linux", target_os = "dragonfly", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))'.dependencies]
 gtk = { version = "0.18", features = ["v3_24"] }
 webkit2gtk = { version = "=2.0.1", features = ["v2_40"] }
 
@@ -120,15 +118,23 @@ objc2-app-kit = { version = "0.2", default-features = false, features = [
 ] }
 window-vibrancy = "0.5"
 
+# windows
 [target."cfg(windows)".dependencies]
 webview2-com = "0.34"
 window-vibrancy = "0.5"
+windows = { version = "0.58", features = ["Win32_Foundation"] }
 
-[target."cfg(windows)".dependencies.windows]
-version = "0.58"
-features = ["Win32_Foundation"]
+# mobile
+[target.'cfg(any(target_os = "android", all(target_vendor = "apple", not(target_os = "macos"))))'.dependencies]
+bytes = { version = "1", features = ["serde"] }
+reqwest = { version = "0.12", default-features = false, features = [
+  "json",
+  "stream",
+  "rustls-tls",
+] }
 
-[target."cfg(target_os = \"android\")".dependencies]
+# android
+[target.'cfg(target_os = "android")'.dependencies]
 jni = "0.21"
 
 # UIKit, i.e. iOS/tvOS/watchOS/visionOS
@@ -179,9 +185,11 @@ objc-exception = ["tauri-runtime-wry/objc-exception"]
 linux-libxdo = ["tray-icon/libxdo", "muda/libxdo"]
 isolation = ["tauri-utils/isolation", "tauri-macros/isolation", "uuid"]
 custom-protocol = ["tauri-macros/custom-protocol"]
+# TODO: Remove these flags in v3 and/or enable them by default behind a mobile flag https://github.com/tauri-apps/tauri/issues/12384
+# For now those feature flags keep enabling reqwest features in case some users depend on that by accident.
 native-tls = ["reqwest/native-tls"]
 native-tls-vendored = ["reqwest/native-tls-vendored"]
-rustls-tls = ["reqwest/rustls-tls"]
+rustls-tls = []
 devtools = ["tauri-runtime/devtools", "tauri-runtime-wry/devtools"]
 process-relaunch-dangerous-allow-symlink-macos = [
   "tauri-utils/process-relaunch-dangerous-allow-symlink-macos",
diff --git a/crates/tauri/src/protocol/tauri.rs b/crates/tauri/src/protocol/tauri.rs
index cded6f615455..c9753c69e848 100644
--- a/crates/tauri/src/protocol/tauri.rs
+++ b/crates/tauri/src/protocol/tauri.rs
@@ -115,6 +115,7 @@ fn get_response<R: Runtime>(
     );
 
     let mut proxy_builder = reqwest::ClientBuilder::new()
+      .use_rustls_tls()
       .build()
       .unwrap()
       .request(request.method().clone(), &url);


Test patch: