`Location::query_map`: support repeated key (#4183)

This adds support for parsing e.g. `?foo=hello&foo=world`, returning
both "hello" and "world" in `Location::query_map`
This commit is contained in:
Emil Ernerfeldt 2024-03-17 17:50:33 +01:00 committed by GitHub
parent 3258cd2a7f
commit 820fa3c43a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 15 deletions

View File

@ -758,8 +758,8 @@ pub struct Location {
/// The parsed "query" part of "www.example.com/index.html?query#fragment".
///
/// "foo=42&bar%20" is parsed as `{"foo": "42", "bar ": ""}`
pub query_map: std::collections::BTreeMap<String, String>,
/// "foo=hello&bar%20&foo=world" is parsed as `{"bar ": [""], "foo": ["hello", "world"]}`
pub query_map: std::collections::BTreeMap<String, Vec<String>>,
/// `location.origin`
///

View File

@ -117,21 +117,24 @@ pub fn web_location() -> epi::Location {
}
/// query is percent-encoded
fn parse_query_map(query: &str) -> BTreeMap<String, String> {
query
.split('&')
.filter_map(|pair| {
if pair.is_empty() {
None
fn parse_query_map(query: &str) -> BTreeMap<String, Vec<String>> {
let mut map: BTreeMap<String, Vec<String>> = Default::default();
for pair in query.split('&') {
if !pair.is_empty() {
if let Some((key, value)) = pair.split_once('=') {
map.entry(percent_decode(key))
.or_default()
.push(percent_decode(value));
} else {
Some(if let Some((key, value)) = pair.split_once('=') {
(percent_decode(key), percent_decode(value))
} else {
(percent_decode(pair), String::new())
})
map.entry(percent_decode(pair))
.or_default()
.push(String::new());
}
})
.collect()
}
}
map
}
// TODO(emilk): this test is never acgtually run, because this whole module is wasm32 only 🤦‍♂️