diff --git a/crates/eframe/src/epi.rs b/crates/eframe/src/epi.rs index 72ad27b80b7..a27a37335cc 100644 --- a/crates/eframe/src/epi.rs +++ b/crates/eframe/src/epi.rs @@ -718,7 +718,7 @@ pub struct WebInfo { #[cfg(target_arch = "wasm32")] #[derive(Clone, Debug)] pub struct Location { - /// The full URL (`location.href`) without the hash. + /// The full URL (`location.href`) without the hash, percent-decoded. /// /// Example: `"http://www.example.com:80/index.html?foo=bar"`. pub url: String, diff --git a/crates/eframe/src/web/backend.rs b/crates/eframe/src/web/backend.rs index 2dc3af4e9ac..1121cb43782 100644 --- a/crates/eframe/src/web/backend.rs +++ b/crates/eframe/src/web/backend.rs @@ -99,28 +99,25 @@ pub fn web_location() -> epi::Location { .search() .unwrap_or_default() .strip_prefix('?') - .map(percent_decode) - .unwrap_or_default(); - - let query_map = parse_query_map(&query) - .iter() - .map(|(k, v)| ((*k).to_owned(), (*v).to_owned())) - .collect(); + .unwrap_or_default() + .to_owned(); epi::Location { + // TODO(emilk): should we really percent-decode the url? 🤷‍♂️ url: percent_decode(&location.href().unwrap_or_default()), protocol: percent_decode(&location.protocol().unwrap_or_default()), host: percent_decode(&location.host().unwrap_or_default()), hostname: percent_decode(&location.hostname().unwrap_or_default()), port: percent_decode(&location.port().unwrap_or_default()), hash, + query_map: parse_query_map(&query), query, - query_map, origin: percent_decode(&location.origin().unwrap_or_default()), } } -fn parse_query_map(query: &str) -> BTreeMap<&str, &str> { +/// query is percent-encoded +fn parse_query_map(query: &str) -> BTreeMap { query .split('&') .filter_map(|pair| { @@ -128,15 +125,16 @@ fn parse_query_map(query: &str) -> BTreeMap<&str, &str> { None } else { Some(if let Some((key, value)) = pair.split_once('=') { - (key, value) + (percent_decode(key), percent_decode(value)) } else { - (pair, "") + (percent_decode(pair), String::new()) }) } }) .collect() } +// TODO(emilk): this test is never acgtually run, because this whole module is wasm32 only 🤦‍♂️ #[test] fn test_parse_query() { assert_eq!(parse_query_map(""), BTreeMap::default()); @@ -157,4 +155,11 @@ fn test_parse_query() { parse_query_map("foo&baz&&"), BTreeMap::from_iter([("foo", ""), ("baz", "")]) ); + assert_eq!( + parse_query_map("badger=data.rrd%3Fparam1%3Dfoo%26param2%3Dbar&mushroom=snake"), + BTreeMap::from_iter([ + ("badger", "data.rrd?param1=foo¶m2=bar"), + ("mushroom", "snake") + ]) + ); }