Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/router-macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,9 +532,14 @@ impl RouteEnum {
// Remove any trailing slashes. We parse /route/ and /route in the same way
// Note: we don't use trim because it includes more code
let route = route.strip_suffix('/').unwrap_or(route);
let query = dioxus_router::exports::percent_encoding::percent_decode_str(query)
// Replace '+' with space in query strings before percent-decoding.
// Per the application/x-www-form-urlencoded spec, '+' is an
// alternative encoding for space in query strings. Some services
// (e.g. Facebook) rewrite '%20' to '+' when processing URLs.
let query_replaced = query.replace('+', " ");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure this actually solves the problem and it might even introduce a new one.

According to RFC 3986, + is a valid literal character in the query component and has no special meaning by default. Forcing application/x-www-form-urlencoded semantics here changes that behavior globally.

I don't think it's a good idea to strictly enforce this interpretation based on behavior of a few services.

let query = dioxus_router::exports::percent_encoding::percent_decode_str(&query_replaced)
.decode_utf8()
.unwrap_or(query.into());
.unwrap_or(query_replaced.into());
let hash = dioxus_router::exports::percent_encoding::percent_decode_str(hash)
.decode_utf8()
.unwrap_or(hash.into());
Expand Down
44 changes: 44 additions & 0 deletions packages/router/tests/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,47 @@ fn optional_query_segments_parse() {
route_without_query_and_other
);
}

// Regression test for https://github.com/DioxusLabs/dioxus/issues/5280
// '+' in query strings should be decoded as space per the
// application/x-www-form-urlencoded spec.
#[test]
fn query_plus_decoded_as_space() {
#[derive(Routable, Clone, PartialEq, Debug)]
enum Route {
#[route("/?:query")]
Home { query: String },
}

#[component]
fn Home(query: String) -> Element {
unimplemented!()
}

// '+' in query value should be parsed as space
let parsed = "/?query=Shis+Kebap".parse::<Route>().unwrap();
assert_eq!(
parsed,
Route::Home {
query: "Shis Kebap".to_string()
}
);

// '%20' should still work as space
let parsed_pct = "/?query=Shis%20Kebap".parse::<Route>().unwrap();
assert_eq!(
parsed_pct,
Route::Home {
query: "Shis Kebap".to_string()
}
);

// Multiple '+' signs
let parsed_multi = "/?query=hello+world+test".parse::<Route>().unwrap();
assert_eq!(
parsed_multi,
Route::Home {
query: "hello world test".to_string()
}
);
}
Loading