Skip to content

Commit 31685c9

Browse files
authored
fix(#2281): Prevent double slashes when joining URLs (#2282)
1 parent 9fbcc02 commit 31685c9

File tree

4 files changed

+38
-16
lines changed

4 files changed

+38
-16
lines changed

.changes/fix-url-concatenation.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri": patch
3+
---
4+
5+
Use [`Url.join()`](https://docs.rs/url/2.2.2/url/struct.Url.html#method.join) when building webview URLs in
6+
`WindowManager`, to handle edge cases and leading/trailing slashes in paths and urls.

core/tauri/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ serde = { version = "1.0", features = [ "derive" ] }
3636
tokio = { version = "1.7", features = [ "rt", "rt-multi-thread", "sync", "fs" ] }
3737
futures = "0.3"
3838
uuid = { version = "0.8", features = [ "v4" ] }
39+
url = { version = "2.2" }
3940
thiserror = "1.0"
4041
once_cell = "1.8"
4142
tauri-runtime = { version = "0.1.4", path = "../tauri-runtime" }

core/tauri/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,10 @@ pub enum Error {
7676
/// Encountered an error creating the app system tray,
7777
#[error("error encountered during tray setup: {0}")]
7878
SystemTray(Box<dyn std::error::Error + Send>),
79+
/// A part of the URL is malformed or invalid. This may occur when parsing and combining
80+
/// user-provided URLs and paths.
81+
#[error("invalid url: {0}")]
82+
InvalidUrl(url::ParseError),
7983
}
8084

8185
impl From<serde_json::Error> for Error {

core/tauri/src/manager.rs

+27-16
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use std::{
4242
sync::{Arc, Mutex, MutexGuard},
4343
};
4444
use tauri_macros::default_runtime;
45+
use url::Url;
4546
use uuid::Uuid;
4647

4748
const WINDOW_RESIZED_EVENT: &str = "tauri://resize";
@@ -180,20 +181,27 @@ impl<R: Runtime> WindowManager<R> {
180181
self.inner.menu_ids.clone()
181182
}
182183

183-
// setup content for dev-server
184+
/// Get the base path to serve data from.
185+
///
186+
/// * In dev mode, this will be based on the `devPath` configuration value.
187+
/// * Otherwise, this will be based on the `distDir` configuration value.
188+
#[cfg(custom_protocol)]
189+
fn base_path(&self) -> &AppUrl {
190+
&self.inner.config.build.dist_dir
191+
}
192+
184193
#[cfg(dev)]
185-
fn get_url(&self) -> String {
186-
match &self.inner.config.build.dev_path {
187-
AppUrl::Url(WindowUrl::External(url)) => url.to_string(),
188-
_ => "tauri://localhost".into(),
189-
}
194+
fn base_path(&self) -> &AppUrl {
195+
&self.inner.config.build.dev_path
190196
}
191197

192-
#[cfg(custom_protocol)]
193-
fn get_url(&self) -> String {
194-
match &self.inner.config.build.dist_dir {
195-
AppUrl::Url(WindowUrl::External(url)) => url.to_string(),
196-
_ => "tauri://localhost".into(),
198+
/// Get the base URL to use for webview requests.
199+
///
200+
/// In dev mode, this will be based on the `devPath` configuration value.
201+
fn get_url(&self) -> Cow<'_, Url> {
202+
match self.base_path() {
203+
AppUrl::Url(WindowUrl::External(url)) => Cow::Borrowed(url),
204+
_ => Cow::Owned(Url::parse("tauri://localhost").unwrap()),
197205
}
198206
}
199207

@@ -505,10 +513,10 @@ mod test {
505513
);
506514

507515
#[cfg(custom_protocol)]
508-
assert_eq!(manager.get_url(), "tauri://localhost");
516+
assert_eq!(manager.get_url().to_string(), "tauri://localhost");
509517

510518
#[cfg(dev)]
511-
assert_eq!(manager.get_url(), "http://localhost:4000/");
519+
assert_eq!(manager.get_url().to_string(), "http://localhost:4000/");
512520
}
513521
}
514522

@@ -561,13 +569,16 @@ impl<R: Runtime> WindowManager<R> {
561569
true,
562570
// ignore "index.html" just to simplify the url
563571
if path.to_str() != Some("index.html") {
564-
format!("{}/{}", url, path.to_string_lossy())
565-
} else {
566572
url
573+
.join(&*path.to_string_lossy())
574+
.map_err(crate::Error::InvalidUrl)?
575+
.to_string()
576+
} else {
577+
url.to_string()
567578
},
568579
)
569580
}
570-
WindowUrl::External(url) => (url.as_str().starts_with("tauri://"), url.to_string()),
581+
WindowUrl::External(url) => (url.scheme() == "tauri", url.to_string()),
571582
_ => unimplemented!(),
572583
};
573584

0 commit comments

Comments
 (0)