Skip to content

Copy query parameter lists when building UriComponents - #37431

Open
cookie-meringue wants to merge 1 commit into
spring-projects:mainfrom
cookie-meringue:fix-query-param-sharing-in-uri-components
Open

cookie-meringue wants to merge 1 commit into
spring-projects:mainfrom
cookie-meringue:fix-query-param-sharing-in-uri-components

Conversation

@cookie-meringue

Copy link
Copy Markdown
Contributor

Current behavior

UriComponentsBuilder.build() copies the query parameter map but not the lists of values stored in it.
The builder and the resulting UriComponents can therefore share mutable query parameter lists.

Problem

Adding a value to an existing query parameter after build() can change the query of an earlier UriComponents result.

UriComponentsBuilder builder =
        UriComponentsBuilder.fromUriString("https://example.org?q=one");
UriComponents first = builder.build();
builder.queryParam("q", "two");
System.out.println(first.toUriString());
// https://example.org?q=one&q=two

A caller that retains first can therefore get a different URI when it uses the result later.

Fix

buildInternal() now creates a new LinkedMultiValueMap and copies the parameters with addAll(...), which creates an independent value list for each key.
The same example now produces:

UriComponentsBuilder builder =
        UriComponentsBuilder.fromUriString("https://example.org?q=one");
UriComponents first = builder.build();
builder.queryParam("q", "two");
System.out.println(first.toUriString());
// https://example.org?q=one

UriComponentsBuilder.build() copies the query parameter map but shares
the value lists for keys already present. Adding another value to one
of those keys after build() changes the earlier UriComponents. Adding
a new key does not, since the map itself was copied.

Copy each query parameter list during build so earlier results keep
their original queries.

Signed-off-by: cookie-meringue <daehyeon3351@gmail.com>
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Oct 9, 2026
@sbrannen sbrannen added the in: web Issues in web modules (web, webmvc, webflux, websocket) label Oct 9, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: web Issues in web modules (web, webmvc, webflux, websocket) status: waiting-for-triage An issue we've not yet triaged or decided on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants