Add IPv6 support in RestTemplate
Prior to this commit, RestTemplate would not would not accept IPv6 raw addresses in URLs because UriComponentsBuilder would not parse/encode the Host part correctly. The UriComponentsBuilder now parses and encode raw IPv6 addresses in the "[1abc:2abc:3abc::5ABC:6abc]" format and also supports the use of IPv6 scope_ids (see JDK8 java.net.Inet6Address), like "[1abc:2abc:3abc::5ABC:6abc%eth0]". Issue: SPR-10539
This commit is contained in:
parent
beaf6992b2
commit
2dd4480103
|
@ -182,7 +182,13 @@ final class HierarchicalUriComponents extends UriComponents {
|
|||
}
|
||||
String encodedScheme = encodeUriComponent(this.getScheme(), encoding, Type.SCHEME);
|
||||
String encodedUserInfo = encodeUriComponent(this.userInfo, encoding, Type.USER_INFO);
|
||||
String encodedHost = encodeUriComponent(this.host, encoding, Type.HOST);
|
||||
String encodedHost;
|
||||
if(StringUtils.hasLength(this.host) && this.host.startsWith("[")) {
|
||||
encodedHost = encodeUriComponent(this.host, encoding, Type.HOST_IPV6);
|
||||
} else {
|
||||
encodedHost = encodeUriComponent(this.host, encoding, Type.HOST);
|
||||
}
|
||||
|
||||
PathComponent encodedPath = this.path.encode(encoding);
|
||||
MultiValueMap<String, String> encodedQueryParams =
|
||||
new LinkedMultiValueMap<String, String>(this.queryParams.size());
|
||||
|
@ -468,6 +474,12 @@ final class HierarchicalUriComponents extends UriComponents {
|
|||
return isUnreserved(c) || isSubDelimiter(c);
|
||||
}
|
||||
},
|
||||
HOST_IPV6 {
|
||||
@Override
|
||||
public boolean isAllowed(int c) {
|
||||
return isUnreserved(c) || isSubDelimiter(c) || '[' == c || ']' == c || ':' == c;
|
||||
}
|
||||
},
|
||||
PORT {
|
||||
@Override
|
||||
public boolean isAllowed(int c) {
|
||||
|
|
|
@ -64,7 +64,11 @@ public class UriComponentsBuilder {
|
|||
|
||||
private static final String USERINFO_PATTERN = "([^@/]*)";
|
||||
|
||||
private static final String HOST_PATTERN = "([^/?#:]*)";
|
||||
private static final String HOST_IPv4_PATTERN = "[^\\[/?#:]*";
|
||||
|
||||
private static final String HOST_IPV6_PATTERN = "\\[[\\p{XDigit}\\:\\.]*[%\\p{Alnum}]*\\]";
|
||||
|
||||
private static final String HOST_PATTERN = "("+HOST_IPV6_PATTERN + "|" + HOST_IPv4_PATTERN + ")";
|
||||
|
||||
private static final String PORT_PATTERN = "(\\d*)";
|
||||
|
||||
|
@ -226,7 +230,11 @@ public class UriComponentsBuilder {
|
|||
String scheme = m.group(1);
|
||||
builder.scheme((scheme != null) ? scheme.toLowerCase() : scheme);
|
||||
builder.userInfo(m.group(4));
|
||||
builder.host(m.group(5));
|
||||
String host = m.group(5);
|
||||
if(StringUtils.hasLength(scheme) && !StringUtils.hasLength(host)) {
|
||||
throw new IllegalArgumentException("[" + httpUrl + "] is not a valid HTTP URL");
|
||||
}
|
||||
builder.host(host);
|
||||
String port = m.group(7);
|
||||
if (StringUtils.hasLength(port)) {
|
||||
builder.port(Integer.parseInt(port));
|
||||
|
|
|
@ -169,6 +169,31 @@ public class UriComponentsBuilderTests {
|
|||
assertEquals("https", UriComponentsBuilder.fromHttpUrl("HTTPS://www.google.com").build().getScheme());
|
||||
}
|
||||
|
||||
// SPR-10539
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void fromHttpUrlStringInvalidIPv6Host() throws URISyntaxException {
|
||||
UriComponents result = UriComponentsBuilder
|
||||
.fromHttpUrl("http://[1abc:2abc:3abc::5ABC:6abc:8080/resource").build().encode();
|
||||
}
|
||||
|
||||
// SPR-10539
|
||||
|
||||
@Test
|
||||
public void fromUriStringIPv6Host() throws URISyntaxException {
|
||||
UriComponents result = UriComponentsBuilder
|
||||
.fromUriString("http://[1abc:2abc:3abc::5ABC:6abc]:8080/resource").build().encode();
|
||||
assertEquals("[1abc:2abc:3abc::5ABC:6abc]",result.getHost());
|
||||
|
||||
UriComponents resultWithScopeId = UriComponentsBuilder
|
||||
.fromUriString("http://[1abc:2abc:3abc::5ABC:6abc%eth0]:8080/resource").build().encode();
|
||||
assertEquals("[1abc:2abc:3abc::5ABC:6abc%25eth0]",resultWithScopeId.getHost());
|
||||
|
||||
UriComponents resultIPv4compatible = UriComponentsBuilder
|
||||
.fromUriString("http://[::192.168.1.1]:8080/resource").build().encode();
|
||||
assertEquals("[::192.168.1.1]",resultIPv4compatible.getHost());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void path() throws URISyntaxException {
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromPath("/foo/bar");
|
||||
|
|
Loading…
Reference in New Issue