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
This commit is contained in:
Sam Brannen 2020-06-26 18:30:09 +02:00
parent dd11dbf3b1
commit 9876ca003b
2 changed files with 84 additions and 1 deletions

View File

@ -59,6 +59,7 @@ import org.springframework.web.util.UriComponents.UriTemplateVariables;
* @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 class UriComponentsBuilder implements UriBuilder, Cloneable {
}
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 {

View File

@ -248,6 +248,84 @@ class UriComponentsBuilderTests {
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();