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 506f92b1a9..5403bdcbac 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-2019 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. @@ -551,7 +551,9 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { @Override public UriComponentsBuilder host(@Nullable String host) { this.host = host; - resetSchemeSpecificPart(); + if (host != null) { + resetSchemeSpecificPart(); + } return this; } @@ -559,14 +561,18 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { public UriComponentsBuilder port(int port) { Assert.isTrue(port >= -1, "Port must be >= -1"); this.port = String.valueOf(port); - resetSchemeSpecificPart(); + if (port > -1) { + resetSchemeSpecificPart(); + } return this; } @Override public UriComponentsBuilder port(@Nullable String port) { this.port = port; - resetSchemeSpecificPart(); + if (port != null) { + resetSchemeSpecificPart(); + } return this; } @@ -604,11 +610,11 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { String value = matcher.group(3); queryParam(name, (value != null ? value : (StringUtils.hasLength(eq) ? "" : null))); } + resetSchemeSpecificPart(); } else { this.queryParams.clear(); } - resetSchemeSpecificPart(); return this; } @@ -617,8 +623,8 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { this.queryParams.clear(); if (query != null) { query(query); + resetSchemeSpecificPart(); } - resetSchemeSpecificPart(); return this; } @@ -651,6 +657,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { public UriComponentsBuilder queryParams(@Nullable MultiValueMap params) { if (params != null) { this.queryParams.addAll(params); + resetSchemeSpecificPart(); } return this; } 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 011a3d77a7..4d6166ebba 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-2019 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. @@ -769,6 +769,21 @@ public class UriComponentsBuilderTests { assertThat(uriComponents.getQueryParams().get("bar").get(0)).isNull(); } + @Test // gh-24444 + public void opaqueUriDoesNotResetOnNullInput() throws URISyntaxException { + URI uri = new URI("urn:ietf:wg:oauth:2.0:oob"); + UriComponents result = UriComponentsBuilder.fromUri(uri) + .host(null) + .port(-1) + .port(null) + .queryParams(null) + .replaceQuery(null) + .query(null) + .build(); + + assertThat(result.toUri()).isEqualTo(uri); + } + @Test public void relativeUrls() { String baseUrl = "https://example.com";