diff --git a/docs/src/main/asciidoc/_configprops.adoc b/docs/src/main/asciidoc/_configprops.adoc index 75a732df..eb1eaef4 100644 --- a/docs/src/main/asciidoc/_configprops.adoc +++ b/docs/src/main/asciidoc/_configprops.adoc @@ -61,6 +61,7 @@ |spring.cloud.consul.enabled | `true` | Is spring cloud consul enabled. |spring.cloud.consul.host | `localhost` | Consul agent hostname. Defaults to 'localhost'. |spring.cloud.consul.port | `8500` | Consul agent port. Defaults to '8500'. +|spring.cloud.consul.path | | Custom path in case consul is running behind a reverse proxy under non-root path. |spring.cloud.consul.retry.enabled | `true` | If consul retry is enabled. |spring.cloud.consul.retry.initial-interval | `1000` | Initial retry interval in milliseconds. |spring.cloud.consul.retry.max-attempts | `6` | Maximum number of attempts. @@ -75,4 +76,4 @@ |spring.cloud.consul.tls.key-store-password | | Password to an external keystore. |spring.cloud.consul.tls.key-store-path | | Path to an external keystore. -|=== \ No newline at end of file +|=== diff --git a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java index a9132ee7..fa983841 100644 --- a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java +++ b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulAutoConfiguration.java @@ -18,6 +18,7 @@ package org.springframework.cloud.consul; import com.ecwid.consul.transport.TLSConfig; import com.ecwid.consul.v1.ConsulClient; +import com.ecwid.consul.v1.ConsulRawClient; import org.aspectj.lang.annotation.Aspect; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint; @@ -58,17 +59,27 @@ public class ConsulAutoConfiguration { } public static ConsulClient createConsulClient(ConsulProperties consulProperties) { - final int agentPort = consulProperties.getPort(); - final String agentHost = !StringUtils.isEmpty(consulProperties.getScheme()) + final String agentPath = consulProperties.getPath(); + final String agentHost = StringUtils.hasLength(consulProperties.getScheme()) ? consulProperties.getScheme() + "://" + consulProperties.getHost() : consulProperties.getHost(); + final ConsulRawClient.Builder builder = ConsulRawClient.Builder.builder().setHost(agentHost) + .setPort(consulProperties.getPort()); if (consulProperties.getTls() != null) { ConsulProperties.TLSConfig tls = consulProperties.getTls(); TLSConfig tlsConfig = new TLSConfig(tls.getKeyStoreInstanceType(), tls.getCertificatePath(), tls.getCertificatePassword(), tls.getKeyStorePath(), tls.getKeyStorePassword()); - return new ConsulClient(agentHost, agentPort, tlsConfig); + builder.setTlsConfig(tlsConfig); } - return new ConsulClient(agentHost, agentPort); + + if (StringUtils.hasLength(agentPath)) { + String normalizedAgentPath = StringUtils.trimTrailingCharacter(agentPath, '/'); + normalizedAgentPath = StringUtils.trimLeadingCharacter(normalizedAgentPath, '/'); + + builder.setPath(normalizedAgentPath); + } + + return new ConsulClient(builder.build()); } @Configuration(proxyBeanMethods = false) diff --git a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulProperties.java b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulProperties.java index 6045ef66..f898be83 100644 --- a/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulProperties.java +++ b/spring-cloud-consul-core/src/main/java/org/springframework/cloud/consul/ConsulProperties.java @@ -55,9 +55,12 @@ public class ConsulProperties { /** Is spring cloud consul enabled. */ private boolean enabled = true; - /** configuration for TLS. */ + /** Configuration for TLS. */ private TLSConfig tls; + /** Custom path if consul is under non-root. */ + private String path; + public String getHost() { return this.host; } @@ -98,10 +101,18 @@ public class ConsulProperties { this.tls = tls; } + public String getPath() { + return path; + } + + public void setPath(String path) { + this.path = path; + } + @Override public String toString() { return "ConsulProperties{" + "host='" + this.host + '\'' + ", port=" + this.port + ", scheme=" + this.scheme - + ", tls=" + this.tls + ", enabled=" + this.enabled + '}'; + + ", tls=" + this.tls + ", enabled=" + this.enabled + ", path=" + this.path + "}"; } /** diff --git a/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulAutoConfigurationTests.java b/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulAutoConfigurationTests.java index 3bb38156..b7709ae9 100644 --- a/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulAutoConfigurationTests.java +++ b/spring-cloud-consul-core/src/test/java/org/springframework/cloud/consul/ConsulAutoConfigurationTests.java @@ -16,6 +16,8 @@ package org.springframework.cloud.consul; +import java.net.URL; + import com.ecwid.consul.transport.DefaultHttpsTransport; import com.ecwid.consul.transport.HttpTransport; import com.ecwid.consul.v1.ConsulClient; @@ -58,6 +60,22 @@ public class ConsulAutoConfigurationTests { .doesNotHaveBean(ConsulEndpoint.class)); } + @Test + public void customPathConfigured() { + appContextRunner.withPropertyValues("spring.cloud.consul.path=/consul/proxy/").run(context -> { + assertThat(context).hasNotFailed().hasSingleBean(ConsulClient.class); + + ConsulClient consulClient = context.getBean(ConsulClient.class); + CatalogConsulClient client = (CatalogConsulClient) ReflectionTestUtils.getField(consulClient, + "catalogClient"); + ConsulRawClient rawClient = (ConsulRawClient) ReflectionTestUtils.getField(client, "rawClient"); + String agentAddress = (String) ReflectionTestUtils.getField(rawClient, "agentAddress"); + + assertThat(agentAddress).isNotNull(); + assertThat(new URL(agentAddress).getPath()).isEqualTo("/consul/proxy"); + }); + } + @Test public void tlsConfigured() { appContextRunner.withPropertyValues("spring.cloud.consul.tls.key-store-instance-type=JKS",