From 52154ed8bb95aaac9925bd95b40643a4ede14589 Mon Sep 17 00:00:00 2001 From: Andy Bodnar Date: Fri, 16 Jan 2026 23:43:02 -0700 Subject: [PATCH] feat(path): add convert_file_src to PathResolver with HTTPS support Adds a Rust equivalent of the JavaScript `convertFileSrc` function to the PathResolver API, enabling file-to-URL conversion from Rust code. This is useful when processing file paths in Rust (e.g., parsing markdown with image references) and needing to convert them to URLs that the webview can load. The implementation: - Uses percent-encoding for URL-safe path encoding - Uses dunce::simplified to normalize Windows paths - Returns HTTP URLs on Windows/Android and custom protocol URLs elsewhere - Adds `use_https` parameter to support webviews with `use_https_scheme` enabled Closes #12022 --- .changes/convert-file-src-https.md | 5 +++ crates/tauri/src/path/android.rs | 40 ++++++++++++++++++++++++ crates/tauri/src/path/desktop.rs | 49 ++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 .changes/convert-file-src-https.md diff --git a/.changes/convert-file-src-https.md b/.changes/convert-file-src-https.md new file mode 100644 index 000000000..9ba8d29ab --- /dev/null +++ b/.changes/convert-file-src-https.md @@ -0,0 +1,5 @@ +--- +"tauri": patch:feat +--- + +Add `use_https` parameter to `PathResolver::convert_file_src` to support webviews with `use_https_scheme` enabled. diff --git a/crates/tauri/src/path/android.rs b/crates/tauri/src/path/android.rs index 451032ee7..a03f95013 100644 --- a/crates/tauri/src/path/android.rs +++ b/crates/tauri/src/path/android.rs @@ -4,6 +4,7 @@ use super::Result; use crate::{plugin::PluginHandle, Runtime}; +use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use std::path::{Path, PathBuf}; /// A helper class to access the mobile path APIs. @@ -175,4 +176,43 @@ impl PathResolver { pub fn home_dir(&self) -> Result { self.call_resolve("getHomeDir") } + + /// Converts a file path to a URL that can be loaded by the webview. + /// + /// This is the Rust equivalent of the JavaScript `convertFileSrc` function. + /// Note: The file must be allowed by the app's asset scope for the webview to load it. + /// + /// # Arguments + /// + /// * `path` - The file path to convert + /// * `protocol` - The protocol to use, defaults to `"asset"` if `None` + /// * `use_https` - Whether to use HTTPS scheme instead of HTTP. + /// Set to `true` if your webview has `use_https_scheme` enabled. Defaults to `false` if `None`. + /// + /// # Examples + /// + /// ```rust,no_run + /// use tauri::Manager; + /// tauri::Builder::default() + /// .setup(|app| { + /// let video_path = app.path().app_data_dir()?.join("video.mp4"); + /// let url = app.path().convert_file_src(&video_path, None, None); + /// // On Android: http://asset.localhost/... + /// println!("URL: {}", url); + /// + /// // With HTTPS enabled: + /// let https_url = app.path().convert_file_src(&video_path, None, Some(true)); + /// // On Android: https://asset.localhost/... + /// println!("HTTPS URL: {}", https_url); + /// Ok(()) + /// }); + /// ``` + pub fn convert_file_src>(&self, path: P, protocol: Option<&str>, use_https: Option) -> String { + let protocol = protocol.unwrap_or("asset"); + let path = path.as_ref(); + let encoded = utf8_percent_encode(&path.to_string_lossy(), NON_ALPHANUMERIC).to_string(); + + let scheme = if use_https.unwrap_or(false) { "https" } else { "http" }; + format!("{scheme}://{protocol}.localhost/{encoded}") + } } diff --git a/crates/tauri/src/path/desktop.rs b/crates/tauri/src/path/desktop.rs index 96ea0bd7e..0aad9f2d5 100644 --- a/crates/tauri/src/path/desktop.rs +++ b/crates/tauri/src/path/desktop.rs @@ -4,6 +4,7 @@ use super::{Error, Result}; use crate::{AppHandle, Manager, Runtime}; +use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use std::path::{Path, PathBuf}; /// The path resolver is a helper class for general and application-specific path APIs. @@ -293,4 +294,52 @@ impl PathResolver { pub fn temp_dir(&self) -> Result { Ok(std::env::temp_dir()) } + + /// Converts a file path to a URL that can be loaded by the webview. + /// + /// This is the Rust equivalent of the JavaScript `convertFileSrc` function. + /// Note: The file must be allowed by the app's asset scope for the webview to load it. + /// + /// # Arguments + /// + /// * `path` - The file path to convert + /// * `protocol` - The protocol to use, defaults to `"asset"` if `None` + /// * `use_https` - Whether to use HTTPS scheme instead of HTTP (Windows only). + /// Set to `true` if your webview has `use_https_scheme` enabled. Defaults to `false` if `None`. + /// + /// # Examples + /// + /// ```rust,no_run + /// use tauri::Manager; + /// tauri::Builder::default() + /// .setup(|app| { + /// let video_path = app.path().app_data_dir()?.join("video.mp4"); + /// let url = app.path().convert_file_src(&video_path, None, None); + /// // On Windows: http://asset.localhost/C%3A%5CUsers%5C... + /// // On macOS/Linux: asset://localhost/%2FUsers%2F... + /// println!("URL: {}", url); + /// + /// // With HTTPS enabled (Windows): + /// let https_url = app.path().convert_file_src(&video_path, None, Some(true)); + /// // On Windows: https://asset.localhost/C%3A%5CUsers%5C... + /// println!("HTTPS URL: {}", https_url); + /// Ok(()) + /// }); + /// ``` + pub fn convert_file_src>(&self, path: P, protocol: Option<&str>, use_https: Option) -> String { + let protocol = protocol.unwrap_or("asset"); + let path = dunce::simplified(path.as_ref()); + let encoded = utf8_percent_encode(&path.to_string_lossy(), NON_ALPHANUMERIC).to_string(); + + #[cfg(windows)] + { + let scheme = if use_https.unwrap_or(false) { "https" } else { "http" }; + format!("{scheme}://{protocol}.localhost/{encoded}") + } + #[cfg(not(windows))] + { + let _ = use_https; // unused on non-Windows platforms + format!("{protocol}://localhost/{encoded}") + } + } }