Support port URI template variables

This commit makes it possible to specify port with an URI template variable.

For example :
RestTemplate restTemplate = new RestTemplate();
restTemplate.getForObject("http://localhost:{port}/resource", String.class, 8080);

Issue: SPR-12123
This commit is contained in:
Sebastien Deleuze 2014-08-28 16:20:28 +02:00 committed by Rossen Stoyanchev
parent 0b02551e2f
commit 8fbd310b07
5 changed files with 59 additions and 15 deletions

View File

@ -52,7 +52,7 @@ final class HierarchicalUriComponents extends UriComponents {
private final String host;
private final int port;
private final String port;
private final PathComponent path;
@ -73,7 +73,7 @@ final class HierarchicalUriComponents extends UriComponents {
* @param encoded whether the components are already encoded
* @param verify whether the components need to be checked for illegal characters
*/
HierarchicalUriComponents(String scheme, String userInfo, String host, int port, PathComponent path,
HierarchicalUriComponents(String scheme, String userInfo, String host, String port, PathComponent path,
MultiValueMap<String, String> queryParams, String fragment, boolean encoded, boolean verify) {
super(scheme, fragment);
@ -109,7 +109,7 @@ final class HierarchicalUriComponents extends UriComponents {
@Override
public int getPort() {
return this.port;
return Integer.parseInt(this.port);
}
@Override
@ -308,6 +308,7 @@ final class HierarchicalUriComponents extends UriComponents {
String expandedScheme = expandUriComponent(getScheme(), uriVariables);
String expandedUserInfo = expandUriComponent(this.userInfo, uriVariables);
String expandedHost = expandUriComponent(this.host, uriVariables);
String expandedPort = expandUriComponent(this.port, uriVariables);
PathComponent expandedPath = this.path.expand(uriVariables);
MultiValueMap<String, String> expandedQueryParams =
new LinkedMultiValueMap<String, String>(this.queryParams.size());
@ -321,7 +322,7 @@ final class HierarchicalUriComponents extends UriComponents {
expandedQueryParams.put(expandedName, expandedValues);
}
String expandedFragment = expandUriComponent(this.getFragment(), uriVariables);
return new HierarchicalUriComponents(expandedScheme, expandedUserInfo, expandedHost, this.port, expandedPath,
return new HierarchicalUriComponents(expandedScheme, expandedUserInfo, expandedHost, expandedPort, expandedPath,
expandedQueryParams, expandedFragment, false, false);
}
@ -359,7 +360,7 @@ final class HierarchicalUriComponents extends UriComponents {
if (this.host != null) {
uriBuilder.append(host);
}
if (this.port != -1) {
if (!"-1".equals(this.port)) {
uriBuilder.append(':');
uriBuilder.append(port);
}
@ -432,7 +433,7 @@ final class HierarchicalUriComponents extends UriComponents {
int result = ObjectUtils.nullSafeHashCode(getScheme());
result = 31 * result + ObjectUtils.nullSafeHashCode(this.userInfo);
result = 31 * result + ObjectUtils.nullSafeHashCode(this.host);
result = 31 * result + this.port;
result = 31 * result + ObjectUtils.nullSafeHashCode(this.port);
result = 31 * result + this.path.hashCode();
result = 31 * result + this.queryParams.hashCode();
result = 31 * result + ObjectUtils.nullSafeHashCode(getFragment());

View File

@ -70,7 +70,7 @@ public class UriComponentsBuilder {
private static final String HOST_PATTERN = "(" + HOST_IPV6_PATTERN + "|" + HOST_IPV4_PATTERN + ")";
private static final String PORT_PATTERN = "(\\d*)";
private static final String PORT_PATTERN = "(\\d*(?:\\{[^/]+?\\})?)";
private static final String PATH_PATTERN = "([^?#]*)";
@ -96,7 +96,7 @@ public class UriComponentsBuilder {
private String host;
private int port = -1;
private String port = "-1";
private CompositePathComponentBuilder pathBuilder = new CompositePathComponentBuilder();
@ -192,7 +192,7 @@ public class UriComponentsBuilder {
builder.userInfo(userInfo);
builder.host(host);
if (StringUtils.hasLength(port)) {
builder.port(Integer.parseInt(port));
builder.port(port);
}
builder.path(path);
builder.query(query);
@ -237,7 +237,7 @@ public class UriComponentsBuilder {
builder.host(host);
String port = m.group(7);
if (StringUtils.hasLength(port)) {
builder.port(Integer.parseInt(port));
builder.port(port);
}
builder.path(m.group(8));
builder.query(m.group(10));
@ -272,7 +272,7 @@ public class UriComponentsBuilder {
return new OpaqueUriComponents(this.scheme, this.ssp, this.fragment);
}
else {
return new HierarchicalUriComponents(this.scheme, this.userInfo, this.host, this.port,
return new HierarchicalUriComponents(this.scheme, this.userInfo, this.host, String.valueOf(this.port),
this.pathBuilder.build(), this.queryParams, this.fragment, encoded, true);
}
}
@ -333,7 +333,7 @@ public class UriComponentsBuilder {
this.host = uri.getHost();
}
if (uri.getPort() != -1) {
this.port = uri.getPort();
this.port = String.valueOf(uri.getPort());
}
if (StringUtils.hasLength(uri.getRawPath())) {
this.pathBuilder = new CompositePathComponentBuilder(uri.getRawPath());
@ -353,7 +353,7 @@ public class UriComponentsBuilder {
private void resetHierarchicalComponents() {
this.userInfo = null;
this.host = null;
this.port = -1;
this.port = "-1";
this.pathBuilder = new CompositePathComponentBuilder();
this.queryParams.clear();
}
@ -393,7 +393,7 @@ public class UriComponentsBuilder {
this.host = uriComponents.getHost();
}
if (uriComponents.getPort() != -1) {
this.port = uriComponents.getPort();
this.port = String.valueOf(uriComponents.getPort());
}
if (StringUtils.hasLength(uriComponents.getPath())) {
List<String> segments = uriComponents.getPathSegments();
@ -462,6 +462,18 @@ public class UriComponentsBuilder {
*/
public UriComponentsBuilder port(int port) {
Assert.isTrue(port >= -1, "'port' must not be < -1");
this.port = String.valueOf(port);
resetSchemeSpecificPart();
return this;
}
/**
* Set the URI port. Passing {@code "-1"} will clear the port of this builder.
* The given port may contain URI template variables.
* @param port the URI port
* @return this UriComponentsBuilder
*/
public UriComponentsBuilder port(String port) {
this.port = port;
resetSchemeSpecificPart();
return this;

View File

@ -54,6 +54,7 @@ public class AbstractJettyServerTestCase {
protected static String helloWorld = "H\u00e9llo W\u00f6rld";
protected static int port;
protected static String baseUrl;
protected static MediaType textContentType;
@ -63,7 +64,7 @@ public class AbstractJettyServerTestCase {
@BeforeClass
public static void startJettyServer() throws Exception {
int port = SocketUtils.findAvailableTcpPort();
port = SocketUtils.findAvailableTcpPort();
jettyServer = new Server(port);
baseUrl = "http://localhost:" + port;
ServletContextHandler handler = new ServletContextHandler();

View File

@ -229,6 +229,14 @@ public class RestTemplateIntegrationTests extends AbstractJettyServerTestCase {
assertTrue(s.contains("\"without\":\"without\""));
}
// SPR-12123
@Test
public void serverPort() {
String s = template.getForObject("http://localhost:{port}/get", String.class, port);
assertEquals("Invalid content", helloWorld, s);
}
public interface MyJacksonView1 {};
public interface MyJacksonView2 {};

View File

@ -80,6 +80,28 @@ public class UriComponentsTests {
assertEquals("http://example.com/1 2 3 4", uriComponents.toUriString());
}
// SPR-12123
@Test
public void port() {
UriComponents uriComponents1 = UriComponentsBuilder.fromUriString(
"http://example.com:8080/bar").build();
UriComponents uriComponents2 = UriComponentsBuilder.fromUriString(
"http://example.com/bar").port(8080).build();
UriComponents uriComponents3 = UriComponentsBuilder.fromUriString(
"http://example.com/bar").port("{port}").build().expand(8080);
UriComponents uriComponents4 = UriComponentsBuilder.fromUriString(
"http://example.com/bar").port("808{digit}").build().expand(0);
assertEquals(8080, uriComponents1.getPort());
assertEquals("http://example.com:8080/bar", uriComponents1.toUriString());
assertEquals(8080, uriComponents2.getPort());
assertEquals("http://example.com:8080/bar", uriComponents2.toUriString());
assertEquals(8080, uriComponents3.getPort());
assertEquals("http://example.com:8080/bar", uriComponents3.toUriString());
assertEquals(8080, uriComponents4.getPort());
assertEquals("http://example.com:8080/bar", uriComponents4.toUriString());
}
@Test(expected = IllegalStateException.class)
public void expandEncoded() {
UriComponentsBuilder.fromPath("/{foo}").build().encode().expand("bar");