Skip to content

UriComponentsBuilder.uriComponents doesn't properly clone unmodifiable queryParams [SPR-17256] #21789

Closed
@spring-projects-issues

Description

@spring-projects-issues

Ruslan Stelmachenko opened SPR-17256 and commented

When UriComponentsBuilder.uriComponents clones queryParams from given UriComponents, it leaves them as unmodifiable MultiValueMap.

This prevents to futher adding query params with the same name into the builder.

For example:

UriComponentsBuilder
		.fromUriString("http://localhost:8081")
		.uriComponents(UriComponentsBuilder.fromUriString("/{path}?sort={sort}").build())
		.queryParam("sort", "another_value")
		.build();

The .queryParam("sort", "another_value") line throws an exception on attempt to add another value to unmodifiable MultiValueMap.

While this code works:

UriComponentsBuilder
		.fromUriString("http://localhost:8081/{path}?sort={sort}")
		.queryParam("sort", "another_value")
		.build();

The interested part of code to investigate this problem is:

org.springframework.web.util.HierarchicalUriComponents#copyToUriComponentsBuilder
Here is line builder.queryParams(getQueryParams()) which sets the builder's queryParams to unmodifiable MultiValueMap.

I think we can clone unmodifiable queryParams here to be modifiable, or maybe better inside org.springframework.web.util.UriComponentsBuilder#queryParams methods to make this logic independent of UriComponents implementation.


To make the intention more clear: this pattern of use UriComponentsBuilder is actually used in org.springframework.web.util.DefaultUriBuilderFactory.DefaultUriBuilder#initUriComponentsBuilder where I first faced this problem.

It allows to set baseUrl and then uriString to concatenate them.
So this code also throws an exception:

new DefaultUriBuilderFactory("http://localhost:8081")
		.uriString("/{path}?sort={sort}")
		.queryParam("sort", "another_value")
		.build(params);

Affects: 5.0.8, 5.1 RC2

Issue Links:

Referenced from: commits 2820831, 1d58fac, c06b952

Backported to: 5.0.10

Metadata

Metadata

Assignees

Labels

in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: bugA general bug

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions