From 02adc2d0b87d2523d68d4fa8bf66981de40a8fce Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Fri, 26 Jun 2020 18:30:09 +0200 Subject: [PATCH] Support fragments in UriComponentsBuilder.fromHttpUrl() Prior to this commit, UriComponentsBuilder.fromHttpUrl() threw an IllegalArgumentException if the provided URL contained a fragment. This commit aligns the implementation of fromHttpUrl() with that of fromUriString(), by parsing a fragment and storing it in the builder. Closes gh-25300 --- .../web/util/UriComponentsBuilder.java | 7 +- .../web/util/UriComponentsBuilderTests.java | 78 +++++++++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) 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 8c953234aea5..f07065be85f8 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 @@ -59,6 +59,7 @@ * @author Oliver Gierke * @author Brian Clozel * @author Sebastien Deleuze + * @author Sam Brannen * @since 3.1 * @see #newInstance() * @see #fromPath(String) @@ -95,7 +96,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable { private static final Pattern HTTP_URL_PATTERN = Pattern.compile( "^" + HTTP_PATTERN + "(//(" + USERINFO_PATTERN + "@)?" + HOST_PATTERN + "(:" + PORT_PATTERN + ")?" + ")?" + - PATH_PATTERN + "(\\?" + LAST_PATTERN + ")?"); + PATH_PATTERN + "(\\?" + QUERY_PATTERN + ")?" + "(#" + LAST_PATTERN + ")?"); private static final Pattern FORWARDED_HOST_PATTERN = Pattern.compile("host=\"?([^;,\"]+)\"?"); @@ -288,6 +289,10 @@ public static UriComponentsBuilder fromHttpUrl(String httpUrl) { } builder.path(matcher.group(8)); builder.query(matcher.group(10)); + String fragment = matcher.group(12); + if (StringUtils.hasText(fragment)) { + builder.fragment(fragment); + } return builder; } else { 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 66081e07fbc3..d19c2740a29c 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 @@ -248,6 +248,84 @@ void fromHttpUrlInvalidIPv6Host() { UriComponentsBuilder.fromHttpUrl("http://[1abc:2abc:3abc::5ABC:6abc:8080/resource")); } + @Test + void fromHttpUrlWithoutFragment() { + String httpUrl = "http://localhost:8080/test/print"; + UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build(); + assertThat(uriComponents.getScheme()).isEqualTo("http"); + assertThat(uriComponents.getUserInfo()).isNull(); + assertThat(uriComponents.getHost()).isEqualTo("localhost"); + assertThat(uriComponents.getPort()).isEqualTo(8080); + assertThat(uriComponents.getPath()).isEqualTo("/test/print"); + assertThat(uriComponents.getPathSegments()).isEqualTo(Arrays.asList("test", "print")); + assertThat(uriComponents.getQuery()).isNull(); + assertThat(uriComponents.getFragment()).isNull(); + assertThat(uriComponents.toUri().toString()).isEqualTo(httpUrl); + + httpUrl = "http://user:test@localhost:8080/test/print?foo=bar"; + uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build(); + assertThat(uriComponents.getScheme()).isEqualTo("http"); + assertThat(uriComponents.getUserInfo()).isEqualTo("user:test"); + assertThat(uriComponents.getHost()).isEqualTo("localhost"); + assertThat(uriComponents.getPort()).isEqualTo(8080); + assertThat(uriComponents.getPath()).isEqualTo("/test/print"); + assertThat(uriComponents.getPathSegments()).isEqualTo(Arrays.asList("test", "print")); + assertThat(uriComponents.getQuery()).isEqualTo("foo=bar"); + assertThat(uriComponents.getFragment()).isNull(); + assertThat(uriComponents.toUri().toString()).isEqualTo(httpUrl); + + httpUrl = "http://localhost:8080/test/print?foo=bar"; + uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build(); + assertThat(uriComponents.getScheme()).isEqualTo("http"); + assertThat(uriComponents.getUserInfo()).isNull(); + assertThat(uriComponents.getHost()).isEqualTo("localhost"); + assertThat(uriComponents.getPort()).isEqualTo(8080); + assertThat(uriComponents.getPath()).isEqualTo("/test/print"); + assertThat(uriComponents.getPathSegments()).isEqualTo(Arrays.asList("test", "print")); + assertThat(uriComponents.getQuery()).isEqualTo("foo=bar"); + assertThat(uriComponents.getFragment()).isNull(); + assertThat(uriComponents.toUri().toString()).isEqualTo(httpUrl); + } + + @Test // gh-25300 + void fromHttpUrlWithFragment() { + String httpUrl = "https://example.com#baz"; + UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build(); + assertThat(uriComponents.getScheme()).isEqualTo("https"); + assertThat(uriComponents.getUserInfo()).isNull(); + assertThat(uriComponents.getHost()).isEqualTo("example.com"); + assertThat(uriComponents.getPort()).isEqualTo(-1); + assertThat(uriComponents.getPath()).isNullOrEmpty(); + assertThat(uriComponents.getPathSegments()).isEmpty(); + assertThat(uriComponents.getQuery()).isNull(); + assertThat(uriComponents.getFragment()).isEqualTo("baz"); + assertThat(uriComponents.toUri().toString()).isEqualTo(httpUrl); + + httpUrl = "http://localhost:8080/test/print#baz"; + uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build(); + assertThat(uriComponents.getScheme()).isEqualTo("http"); + assertThat(uriComponents.getUserInfo()).isNull(); + assertThat(uriComponents.getHost()).isEqualTo("localhost"); + assertThat(uriComponents.getPort()).isEqualTo(8080); + assertThat(uriComponents.getPath()).isEqualTo("/test/print"); + assertThat(uriComponents.getPathSegments()).isEqualTo(Arrays.asList("test", "print")); + assertThat(uriComponents.getQuery()).isNull(); + assertThat(uriComponents.getFragment()).isEqualTo("baz"); + assertThat(uriComponents.toUri().toString()).isEqualTo(httpUrl); + + httpUrl = "http://localhost:8080/test/print?foo=bar#baz"; + uriComponents = UriComponentsBuilder.fromHttpUrl(httpUrl).build(); + assertThat(uriComponents.getScheme()).isEqualTo("http"); + assertThat(uriComponents.getUserInfo()).isNull(); + assertThat(uriComponents.getHost()).isEqualTo("localhost"); + assertThat(uriComponents.getPort()).isEqualTo(8080); + assertThat(uriComponents.getPath()).isEqualTo("/test/print"); + assertThat(uriComponents.getPathSegments()).isEqualTo(Arrays.asList("test", "print")); + assertThat(uriComponents.getQuery()).isEqualTo("foo=bar"); + assertThat(uriComponents.getFragment()).isEqualTo("baz"); + assertThat(uriComponents.toUri().toString()).isEqualTo(httpUrl); + } + @Test void fromHttpRequest() { MockHttpServletRequest request = new MockHttpServletRequest();