From 93e42b8e4f161b0830f2173014ba748df8581808 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Mon, 20 Jul 2020 07:35:05 +0200 Subject: [PATCH] Copy queryParams MultiValueMap through deepCopy (for independent List entries) Closes gh-25423 --- .../web/util/UriComponentsBuilder.java | 6 ++--- .../web/util/UriComponentsBuilderTests.java | 22 ++++++++++--------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java index ee1db7b05fe8..83914f21830b 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -108,7 +108,7 @@ public class UriComponentsBuilder implements Cloneable { private CompositePathComponentBuilder pathBuilder; - private final MultiValueMap queryParams = new LinkedMultiValueMap(); + private LinkedMultiValueMap queryParams = new LinkedMultiValueMap(); private String fragment; @@ -135,7 +135,7 @@ protected UriComponentsBuilder(UriComponentsBuilder other) { this.host = other.host; this.port = other.port; this.pathBuilder = other.pathBuilder.cloneBuilder(); - this.queryParams.putAll(other.queryParams); + this.queryParams = other.queryParams.deepCopy(); this.fragment = other.fragment; } 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 7640e6233630..6182c89cc6d2 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ import static org.junit.Assert.*; /** - * Unit tests for {@link org.springframework.web.util.UriComponentsBuilder}. + * Unit tests for {@link UriComponentsBuilder}. * * @author Arjen Poutsma * @author Phillip Webb @@ -557,7 +557,7 @@ public void pathSegmentsSomeEmpty() { } @Test // SPR-12398 - public void pathWithDuplicateSlashes() throws URISyntaxException { + public void pathWithDuplicateSlashes() { UriComponents uriComponents = UriComponentsBuilder.fromPath("/foo/////////bar").build(); assertEquals("/foo/bar", uriComponents.getPath()); } @@ -727,26 +727,28 @@ public void parsesEmptyUri() { assertThat(components.toString(), equalTo("")); } - @Test - public void testClone() throws URISyntaxException { + @Test // gh-25243 + public void testCloneAndMerge() { UriComponentsBuilder builder1 = UriComponentsBuilder.newInstance(); - builder1.scheme("http").host("e1.com").path("/p1").pathSegment("ps1").queryParam("q1").fragment("f1"); + builder1.scheme("http").host("e1.com").path("/p1").pathSegment("ps1").queryParam("q1", "x").fragment("f1"); - UriComponentsBuilder builder2 = (UriComponentsBuilder) builder1.clone(); + UriComponentsBuilder builder2 = builder1.cloneBuilder(); builder2.scheme("https").host("e2.com").path("p2").pathSegment("ps2").queryParam("q2").fragment("f2"); + builder1.queryParam("q1", "y"); // one more entry for an existing parameter + UriComponents result1 = builder1.build(); assertEquals("http", result1.getScheme()); assertEquals("e1.com", result1.getHost()); assertEquals("/p1/ps1", result1.getPath()); - assertEquals("q1", result1.getQuery()); + assertEquals("q1=x&q1=y", result1.getQuery()); assertEquals("f1", result1.getFragment()); - UriComponents result2 = builder2.build(); + UriComponents result2 = builder2.buildAndExpand("ps2;a"); assertEquals("https", result2.getScheme()); assertEquals("e2.com", result2.getHost()); assertEquals("/p1/ps1/p2/ps2", result2.getPath()); - assertEquals("q1&q2", result2.getQuery()); + assertEquals("q1=x&q2", result2.getQuery()); assertEquals("f2", result2.getFragment()); }