leptos-rs / leptos

Build fast web applications with Rust.
https://leptos.dev
MIT License
15.96k stars 627 forks source link

Query parameters are not properly escaped #2602

Closed luxalpa closed 4 months ago

luxalpa commented 4 months ago

Describe the bug Because leptos_router uses js_sys::encode_uri instead of js_sys::encode_uri_component under the hood, it does not escape characters like % and +. In #2601 I fixed the issue. Please note that the fix also revealed an issue with double decoding values, which causes errors with %/%25 in the URL, which I also fixed in the same PR.

Leptos Dependencies leptos = { version = "0.6.11", features = ["nightly"] } leptos_meta = { version = "0.6.11", features = ["nightly"] } leptos_actix = { version = "0.6.11", optional = true } leptos_router = { version = "0.6.11", features = ["nightly"] } leptos_dom = "0.6.11" leptos_reactive = { version = "0.6.11" } leptos_macro = { version = "0.6.11" }

To Reproduce Run the following code, then try to enter + into input.

use leptos::*;
use leptos_meta::*;
use leptos_router::{
    params_map, use_navigate, use_query, NavigateOptions, Params, Route, Router, Routes, SsrMode,
};

#[component]
pub fn App() -> impl IntoView {
    provide_meta_context();

    view! {
        <Router>
            <Routes>
                <Route path="/" view=HomePage ssr=SsrMode::PartiallyBlocked />
            </Routes>
        </Router>
    }
}

#[derive(Clone, PartialEq, Params, Default, Debug)]
struct Query {
    q: String,
}

#[component]
pub fn HomePage() -> impl IntoView {
    let navigate = use_navigate();
    let q = use_query::<Query>();
    let value = move || {
        logging::log!("q: {:?}", q.get());
        q.get().unwrap_or_default().q
    };
    let on_input = move |event| {
        let v = event_target_value(&event);
        let params = params_map! {
            "q" => v,
        };

        navigate(
            &format!("/{}", params.to_query_string()),
            NavigateOptions {
                replace: true,
                ..Default::default()
            },
        );
    };

    view! {
        <h1>Home Page</h1>
        <input type="text" name="q" prop:value=value on:input=on_input />
    }
}

Expected behavior Characters like + show up in the input because they were properly escaped into the query parameters

Actual behavior Instead of a +, we get a space character