Fix url encoding query and implement FromQueryArgument for Option<T> (#4213)

* Fix url encoding queries

* handle percent encoding hash fragments

* implement fromqueryargument for Option<T>

* fix tests

* fix typo
This commit is contained in:
Evan Almloff authored and GitHub committed 2025-06-02 13:14:53 -05:00
1 parent 662cf0d902
commit 9b16cbf254
13 files changed
+294 -30

No files matched your search

+1 -1
View File
@@ -28,7 +28,7 @@ impl HashFragment {
{
let __hash = #ident.to_string();
if !__hash.is_empty() {
write!(f, "#{}", __hash)?;
write!(f, "#{}", dioxus_router::exports::percent_encoding::utf8_percent_encode(&__hash, dioxus_router::exports::FRAGMENT_ASCII_SET))?;
}
}
}
+11 -3
View File
@@ -531,9 +531,17 @@ 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::urlencoding::decode(query).unwrap_or(query.into());
let hash = dioxus_router::exports::urlencoding::decode(hash).unwrap_or(hash.into());
let mut segments = route.split('/').map(|s| dioxus_router::exports::urlencoding::decode(s).unwrap_or(s.into()));
let query = dioxus_router::exports::percent_encoding::percent_decode_str(query)
.decode_utf8()
.unwrap_or(query.into());
let hash = dioxus_router::exports::percent_encoding::percent_decode_str(hash)
.decode_utf8()
.unwrap_or(hash.into());
let mut segments = route.split('/').map(|s| {
dioxus_router::exports::percent_encoding::percent_decode_str(s)
.decode_utf8()
.unwrap_or(s.into())
});
// skip the first empty segment
if s.starts_with('/') {
let _ = segments.next();
+16 -12
View File
@@ -39,13 +39,8 @@ impl QuerySegment {
QuerySegment::Segments(segments) => {
let mut tokens = TokenStream2::new();
tokens.extend(quote! { write!(f, "?")?; });
let mut segments_iter = segments.iter();
if let Some(first_segment) = segments_iter.next() {
tokens.extend(first_segment.write());
}
for segment in segments_iter {
tokens.extend(quote! { write!(f, "&")?; });
tokens.extend(segment.write());
for (i, segment) in segments.iter().enumerate() {
tokens.extend(segment.write(i == segments.len() - 1));
}
tokens
}
@@ -133,7 +128,7 @@ impl FullQuerySegment {
quote! {
{
let as_string = #ident.to_string();
write!(f, "?{}", dioxus_router::exports::urlencoding::encode(&as_string))?;
write!(f, "?{}", dioxus_router::exports::percent_encoding::utf8_percent_encode(&as_string, dioxus_router::exports::QUERY_ASCII_SET))?;
}
}
}
@@ -151,18 +146,27 @@ impl QueryArgument {
let ty = &self.ty;
quote! {
let #ident = match split_query.get(stringify!(#ident)) {
Some(query_argument) => <#ty as dioxus_router::routable::FromQueryArgument>::from_query_argument(query_argument).unwrap_or_default(),
Some(query_argument) => {
use dioxus_router::routable::FromQueryArgument;
<#ty>::from_query_argument(query_argument).unwrap_or_default()
},
None => <#ty as Default>::default(),
};
}
}
pub fn write(&self) -> TokenStream2 {
pub fn write(&self, trailing: bool) -> TokenStream2 {
let ident = &self.ident;
let write_ampersand = if !trailing {
quote! { if !as_string.is_empty() { write!(f, "&")?; } }
} else {
quote! {}
};
quote! {
{
let as_string = #ident.to_string();
write!(f, "{}={}", stringify!(#ident), dioxus_router::exports::urlencoding::encode(&as_string))?;
let as_string = dioxus_router::routable::DisplayQueryArgument::new(stringify!(#ident), #ident).to_string();
write!(f, "{}", dioxus_router::exports::percent_encoding::utf8_percent_encode(&as_string, dioxus_router::exports::QUERY_ASCII_SET))?;
#write_ampersand
}
}
}
+1 -1
View File
@@ -27,7 +27,7 @@ impl RouteSegment {
Self::Dynamic(ident, _) => quote! {
{
let as_string = #ident.to_string();
write!(f, "/{}", dioxus_router::exports::urlencoding::encode(&as_string))?;
write!(f, "/{}", dioxus_router::exports::percent_encoding::utf8_percent_encode(&as_string, dioxus_router::exports::PATH_ASCII_SET))?;
}
},
Self::CatchAll(ident, _) => quote! { #ident.display_route_segments(f)?; },