flow icon indicating copy to clipboard operation
flow copied to clipboard

fix: preserve URL-encoded characters in wildcard route parameters

Open Artur- opened this issue 4 months ago • 3 comments

Fixes #19788

Changes:

  • Client: Remove premature decoding of pathname in Flow.ts to preserve encoded characters like %2F in the URL sent to server
  • Server: Add PathUtil.getSegmentsListWithDecoding() method that splits path by "/" then decodes each segment individually
  • Server: Update RouteSegment to use segment decoding for route matching

This fix ensures that URL-encoded slashes (%2F) and other special characters in wildcard parameters are properly decoded while still distinguishing them from literal path separators. For example:

  • /wild/a/b/c creates 3 segments: ["a", "b", "c"]
  • /wild/a%2Fb%2Fc creates 1 segment that decodes to: ["a/b/c"]

Previously, the client decoded the entire pathname causing %2F to become "/" which the server then incorrectly split as path segments, resulting in data loss.

Tests added:

  • PathUtil segment decoding with various encoded characters
  • Wildcard parameter routing with encoded slashes and special chars
  • URL generation documentation for pre-encoding requirements

Artur- avatar Nov 19 '25 14:11 Artur-

Test Results

1 243 files   -  65  1 243 suites   - 65   1h 8m 40s ⏱️ - 7m 35s 9 089 tests  - 107  9 023 ✅  - 105  65 💤  - 3  1 ❌ +1  9 467 runs   - 186  9 394 ✅  - 183  72 💤  - 4  1 ❌ +1 

For more details on these failures, see this check.

Results for commit d973b4bf. ± Comparison against base commit 54ea58c5.

This pull request removes 125 and adds 18 tests. Note that renamed tests count towards both.
com.vaadin.flow.AddQueryParamIT(production) ‑ validateRouterInUse[any_Chrome_]
com.vaadin.flow.FlowInReactComponentIT(production) ‑ validateComponentPlacesAndFunction[any_Chrome_]
com.vaadin.flow.HistoryIT(production) ‑ testHistory[any_Chrome_]
com.vaadin.flow.NavigationEventsIT(production) ‑ assertNavigationToSelfProducesNavigationEvents[any_Chrome_]
com.vaadin.flow.NavigationTriggerIT(production) ‑ testNavigationTriggers[any_Chrome_]
com.vaadin.flow.PopStateHandlerIT(production) ‑ testDifferentPath_ServerSideEvent[any_Chrome_]
com.vaadin.flow.PopStateHandlerIT(production) ‑ testDifferentPath_doubleBack_ServerSideEvent[any_Chrome_]
com.vaadin.flow.PopStateHandlerIT(production) ‑ testSamePathHashChanges_noServerSideEvent[any_Chrome_]
com.vaadin.flow.PopStateHandlerIT(production) ‑ testSamePathHashChanges_tripleeBack_noServerSideEvent[any_Chrome_]
com.vaadin.flow.PostponeProceedIT(production) ‑ proceedPostponedNavigationImmediately_navigationIsDone[any_Chrome_]
…
com.vaadin.flow.router.RouterConfigurationUrlResolvingTest ‑ getUrl_with_wildcard_parameter_requires_pre_encoded_special_chars
com.vaadin.flow.router.RouterTest ‑ wildcard_parameter_encoded_vs_literal_slashes
com.vaadin.flow.router.RouterTest ‑ wildcard_parameter_with_encoded_slashes
com.vaadin.flow.router.RouterTest ‑ wildcard_parameter_with_encoded_special_characters
com.vaadin.flow.router.RouterTest ‑ wildcard_parameter_with_mixed_encoded_segments
com.vaadin.flow.router.internal.PathUtilTest ‑ getSegmentsListWithDecoding_decodesEncodedSlashes
com.vaadin.flow.router.internal.PathUtilTest ‑ getSegmentsListWithDecoding_decodesHash
com.vaadin.flow.router.internal.PathUtilTest ‑ getSegmentsListWithDecoding_decodesPercent
com.vaadin.flow.router.internal.PathUtilTest ‑ getSegmentsListWithDecoding_decodesPlus
com.vaadin.flow.router.internal.PathUtilTest ‑ getSegmentsListWithDecoding_decodesSpaces
…

:recycle: This comment has been updated with latest results.

github-actions[bot] avatar Nov 19 '25 15:11 github-actions[bot]

Format Checker Report

BLOCKER There are 3 files with format errors

  • To see a complete report of formatting issues, download the differences artifact

  • To fix the build, please run mvn spotless:apply in your branch and commit the changes.

  • Optionally you might add the following line in your .git/hooks/pre-commit file:

    mvn spotless:apply
    

Here is the list of files with format issues in your PR:

flow-server/src/main/java/com/vaadin/flow/router/internal/PathUtil.java
flow-server/src/test/java/com/vaadin/flow/router/RouterConfigurationUrlResolvingTest.java
flow-server/src/test/java/com/vaadin/flow/router/internal/PathUtilTest.java

github-actions[bot] avatar Dec 15 '25 07:12 github-actions[bot]