diff --git a/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java b/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java index 45521b4d7d94..f2d863197a62 100644 --- a/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java +++ b/spring-web/src/main/java/org/springframework/web/util/HierarchicalUriComponents.java @@ -443,7 +443,7 @@ private MultiValueMap expandQueryParams(UriTemplateVariables var UriTemplateVariables queryVariables = new QueryUriTemplateVariables(variables); this.queryParams.forEach((key, values) -> { String name = expandUriComponent(key, queryVariables, this.variableEncoder); - List expandedValues = new ArrayList<>(values.size()); + List expandedValues = result.getOrDefault(name, new ArrayList<>(values.size())); for (String value : values) { expandedValues.add(expandUriComponent(value, queryVariables, this.variableEncoder)); } diff --git a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java index f31c71bb1a80..6376a680dbcc 100644 --- a/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/UriComponentsBuilderTests.java @@ -629,6 +629,20 @@ void parseBuildAndExpandHierarchical(ParserType parserType) { assertThat(uri.toString()).isEqualTo("ws://example.org:7777/path?q=1#foo"); } + @ParameterizedTest + @EnumSource + void parseBuildAndExpandHierarchicalWithDuplicateQueryKeys(ParserType parserType) { + UriComponents result = UriComponentsBuilder.fromUriString("/?{pk1}={pv1}&{pk2}={pv2}", parserType) + .buildAndExpand("k1", "v1", "k1", "v2"); + assertThat(result.getQuery()).isEqualTo("k1=v1&k1=v2"); + assertThat(result.getQueryParams().get("k1")).containsExactly("v1", "v2"); + + UriComponents result2 = UriComponentsBuilder.fromUriString("/?{pk1}={pv1}&{pk2}={pv2}", parserType) + .buildAndExpand(Map.of("pk1", "k1", "pv1", "v1", "pk2", "k1", "pv2", "v2")); + assertThat(result2.getQuery()).isEqualTo("k1=v1&k1=v2"); + assertThat(result.getQueryParams().get("k1")).containsExactly("v1", "v2"); + } + @ParameterizedTest @EnumSource void buildAndExpandOpaque(ParserType parserType) {