diff --git a/docs/src/main/asciidoc/spring-cloud-config.adoc b/docs/src/main/asciidoc/spring-cloud-config.adoc
index e96656ad..df7ff90f 100644
--- a/docs/src/main/asciidoc/spring-cloud-config.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-config.adoc
@@ -1432,10 +1432,12 @@ NOTE: The `--key` argument is mandatory (despite having a `--` prefix).
=== Key Management
The Config Server can use a symmetric (shared) key or an asymmetric one (RSA key pair).
-The asymmetric choice is superior in terms of security, but it is often more convenient to use a symmetric key since it is a single property value to configure in the `bootstrap.properties`.
+The asymmetric choice is superior in terms of security, but it is often more convenient to use a symmetric key since it is a single property value to configure in the `application.properties`.
To configure a symmetric key, you need to set `encrypt.key` to a secret String (or use the `ENCRYPT_KEY` environment variable to keep it out of plain-text configuration files).
+NOTE: If you include `spring-cloud-starter-bootstrap` on the classpath or set `spring.cloud.bootstrap.enabled=true` as a system property, you will need to set `encrypt.key` in `bootstrap.properties`.
+
NOTE: You cannot configure an asymmetric key using `encrypt.key`.
To configure an asymmetric key use a keystore (e.g. as
diff --git a/pom.xml b/pom.xml
index fadd52b0..842470d8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,10 +30,8 @@
4.0.0-SNAPSHOT
2.17.195
v1-rev20201112-1.30.10
- 1.16.2
+ 1.17.3
2.31.0
- 1.10.0-M3
- 1.0.0-M6
true
true
@@ -106,23 +104,9 @@
pom
import
-
- io.micrometer
- micrometer-bom
- ${micrometer.version}
- pom
- import
-
-
- io.micrometer
- micrometer-tracing-bom
- ${micrometer-tracing.version}
- pom
- import
-
com.github.tomakehurst
- wiremock-jre8
+ wiremock-jre8-standalone
${wiremock.version}
diff --git a/spring-cloud-config-client/src/main/resources/META-INF/spring.factories b/spring-cloud-config-client/src/main/resources/META-INF/spring.factories
index 190b4ce0..e9918536 100644
--- a/spring-cloud-config-client/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-config-client/src/main/resources/META-INF/spring.factories
@@ -1,6 +1,3 @@
-# Auto Configure
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.config.client.ConfigClientAutoConfiguration
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.config.client.ConfigServiceBootstrapConfiguration,\
diff --git a/spring-cloud-config-client/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-config-client/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..e96d07d5
--- /dev/null
+++ b/spring-cloud-config-client/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+org.springframework.cloud.config.client.ConfigClientAutoConfiguration
diff --git a/spring-cloud-config-monitor/src/main/java/org/springframework/cloud/config/monitor/PropertyPathEndpoint.java b/spring-cloud-config-monitor/src/main/java/org/springframework/cloud/config/monitor/PropertyPathEndpoint.java
index e8920b19..b17c71a9 100644
--- a/spring-cloud-config-monitor/src/main/java/org/springframework/cloud/config/monitor/PropertyPathEndpoint.java
+++ b/spring-cloud-config-monitor/src/main/java/org/springframework/cloud/config/monitor/PropertyPathEndpoint.java
@@ -108,22 +108,16 @@ public class PropertyPathEndpoint implements ApplicationEventPublisherAware {
String stem = StringUtils.stripFilenameExtension(StringUtils.getFilename(StringUtils.cleanPath(path)));
// TODO: correlate with service registry
int index = stem.indexOf("-");
- while (index >= 0) {
- String name = stem.substring(0, index);
- String profile = stem.substring(index + 1);
- if ("application".equals(name)) {
- services.add("*:" + profile);
- }
- else if (!name.startsWith("application")) {
- services.add(name + ":" + profile);
- }
- index = stem.indexOf("-", index + 1);
- }
String name = stem;
+ if (index > 0) {
+ name = stem.substring(0, index);
+ }
+ // foo.properties is targeted at the foo application,
+ // while application.properties is targeted at all applications
if ("application".equals(name)) {
services.add("*");
}
- else if (!name.startsWith("application")) {
+ else {
services.add(name);
}
}
diff --git a/spring-cloud-config-monitor/src/main/resources/META-INF/spring.factories b/spring-cloud-config-monitor/src/main/resources/META-INF/spring.factories
deleted file mode 100644
index 66f23537..00000000
--- a/spring-cloud-config-monitor/src/main/resources/META-INF/spring.factories
+++ /dev/null
@@ -1,3 +0,0 @@
-# Autoconfiguration
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.config.monitor.EnvironmentMonitorAutoConfiguration
diff --git a/spring-cloud-config-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-config-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..dd290615
--- /dev/null
+++ b/spring-cloud-config-monitor/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+org.springframework.cloud.config.monitor.EnvironmentMonitorAutoConfiguration
diff --git a/spring-cloud-config-monitor/src/test/java/org/springframework/cloud/config/monitor/PropertyPathEndpointTests.java b/spring-cloud-config-monitor/src/test/java/org/springframework/cloud/config/monitor/PropertyPathEndpointTests.java
index b69151a7..8ac55a7a 100644
--- a/spring-cloud-config-monitor/src/test/java/org/springframework/cloud/config/monitor/PropertyPathEndpointTests.java
+++ b/spring-cloud-config-monitor/src/test/java/org/springframework/cloud/config/monitor/PropertyPathEndpointTests.java
@@ -72,7 +72,7 @@ public class PropertyPathEndpointTests {
public void testNotifyAllWithProfile() {
assertThat(this.endpoint
.notifyByPath(new HttpHeaders(), Collections.singletonMap("path", "application-local.yml")).toString())
- .isEqualTo("[*:local]");
+ .isEqualTo("[*]");
}
@Test
@@ -92,13 +92,13 @@ public class PropertyPathEndpointTests {
@Test
public void testNotifyOneWithProfile() {
assertThat(this.endpoint.notifyByPath(new HttpHeaders(), Collections.singletonMap("path", "foo-local.yml"))
- .toString()).isEqualTo("[foo:local, foo-local]");
+ .toString()).isEqualTo("[foo]");
}
@Test
public void testNotifyMultiDash() {
assertThat(this.endpoint.notifyByPath(new HttpHeaders(), Collections.singletonMap("path", "foo-local-dev.yml"))
- .toString()).isEqualTo("[foo:local-dev, foo-local:dev, foo-local-dev]");
+ .toString()).isEqualTo("[foo]");
}
}
diff --git a/spring-cloud-config-sample/src/test/java/sample/ApplicationBootstrapTests.java b/spring-cloud-config-sample/src/test/java/sample/ApplicationBootstrapTests.java
index 9a7887e4..4e2a1dc1 100644
--- a/spring-cloud-config-sample/src/test/java/sample/ApplicationBootstrapTests.java
+++ b/spring-cloud-config-sample/src/test/java/sample/ApplicationBootstrapTests.java
@@ -53,7 +53,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
// config
// server on the classpath we need to set it explicitly
properties = { "spring.cloud.config.enabled:true", "", "spring.config.use-legacy-processing=true",
- "management.security.enabled=false", "management.endpoints.web.exposure.include=*" },
+ "management.security.enabled=false", "management.endpoints.web.exposure.include=*",
+ "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ApplicationBootstrapTests {
diff --git a/spring-cloud-config-sample/src/test/java/sample/ApplicationTests.java b/spring-cloud-config-sample/src/test/java/sample/ApplicationTests.java
index 2354d156..bffe0d89 100644
--- a/spring-cloud-config-sample/src/test/java/sample/ApplicationTests.java
+++ b/spring-cloud-config-sample/src/test/java/sample/ApplicationTests.java
@@ -44,7 +44,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
properties = { "spring.cloud.config.enabled:true",
// FIXME: configdata why is this needed here?
"spring.config.use-legacy-processing=true", "management.security.enabled=false",
- "management.endpoints.web.exposure.include=*" },
+ "management.endpoints.web.exposure.include=*", "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ApplicationTests {
diff --git a/spring-cloud-config-sample/src/test/java/sample/ConfigDataIntegrationTests.java b/spring-cloud-config-sample/src/test/java/sample/ConfigDataIntegrationTests.java
index 1877428e..eedfd2ca 100644
--- a/spring-cloud-config-sample/src/test/java/sample/ConfigDataIntegrationTests.java
+++ b/spring-cloud-config-sample/src/test/java/sample/ConfigDataIntegrationTests.java
@@ -42,7 +42,8 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
// Normally spring.cloud.config.enabled:true is the default but since we have the
// config server on the classpath we need to set it explicitly
properties = { "spring.cloud.config.enabled=true", "spring.config.import=configserver:",
- "management.security.enabled=false", "management.endpoints.web.exposure.include=*" },
+ "management.security.enabled=false", "management.endpoints.web.exposure.include=*",
+ "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ConfigDataIntegrationTests {
diff --git a/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingIntegrationTests.java b/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingIntegrationTests.java
index 5996741a..c9e5f5a9 100644
--- a/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingIntegrationTests.java
+++ b/spring-cloud-config-sample/src/test/java/sample/ConfigDataOrderingIntegrationTests.java
@@ -45,7 +45,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
// hence no spring.config.import here and config name change
properties = { "spring.application.name=profilesample", "spring.cloud.config.enabled=true",
"spring.config.name=orderingtest", "management.security.enabled=false", "spring.profiles.active=dev",
- "management.endpoints.web.exposure.include=*" },
+ "management.endpoints.web.exposure.include=*", "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ConfigDataOrderingIntegrationTests {
diff --git a/spring-cloud-config-sample/src/test/java/sample/ConfigDataRetryIntegrationTests.java b/spring-cloud-config-sample/src/test/java/sample/ConfigDataRetryIntegrationTests.java
index 195c6cdf..f608fa81 100644
--- a/spring-cloud-config-sample/src/test/java/sample/ConfigDataRetryIntegrationTests.java
+++ b/spring-cloud-config-sample/src/test/java/sample/ConfigDataRetryIntegrationTests.java
@@ -53,7 +53,7 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen
properties = { "spring.application.name=retryapp", "spring.cloud.config.fail-fast=true",
"spring.cloud.config.enabled=true", "spring.config.import=configserver:",
"management.security.enabled=false", "management.endpoints.web.exposure.include=*",
- "logging.level.org.springframework.retry=TRACE" },
+ "logging.level.org.springframework.retry=TRACE", "management.endpoint.env.show-values=ALWAYS" },
webEnvironment = RANDOM_PORT)
public class ConfigDataRetryIntegrationTests {
diff --git a/spring-cloud-config-server/pom.xml b/spring-cloud-config-server/pom.xml
index 0d18879d..9463900f 100644
--- a/spring-cloud-config-server/pom.xml
+++ b/spring-cloud-config-server/pom.xml
@@ -179,7 +179,7 @@
com.github.tomakehurst
- wiremock-jre8
+ wiremock-jre8-standalone
test
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/DefaultTextEncryptionAutoConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/DefaultTextEncryptionAutoConfiguration.java
index 0f4257fa..45aac12c 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/DefaultTextEncryptionAutoConfiguration.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/DefaultTextEncryptionAutoConfiguration.java
@@ -39,7 +39,7 @@ import org.springframework.util.StringUtils;
* Default text encryption auto-configuration.
*
* @author Olga Maciaszek-Sharma
- * @since 3.1.2
+ * @since 4.0.0
*/
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(RsaEncryptionAutoConfiguration.class)
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EncryptionAutoConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EncryptionAutoConfiguration.java
index abb59e17..0c83612f 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EncryptionAutoConfiguration.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/EncryptionAutoConfiguration.java
@@ -30,7 +30,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.encrypt.TextEncryptor;
/**
- * Auto-configuration for text encryptors and environment encryptors (non-web stuff).
+ * Autoconfiguration for text encryptors and environment encryptors (non-web stuff).
* Users can provide beans of the same type as any or all of the beans defined here in
* application code to override the default behaviour.
*
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/RsaEncryptionAutoConfiguration.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/RsaEncryptionAutoConfiguration.java
index 13a5f80e..be84ad25 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/RsaEncryptionAutoConfiguration.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/config/RsaEncryptionAutoConfiguration.java
@@ -31,10 +31,10 @@ import org.springframework.security.rsa.crypto.RsaAlgorithm;
import org.springframework.security.rsa.crypto.RsaSecretEncryptor;
/**
- * Auto-configuration for RSA encryption.
+ * Autoconfiguration for RSA encryption.
*
* @author Olga Maciaszek-Sharma
- * @since 3.1.2
+ * @since 4.0.0
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(prefix = "encrypt.key-store", value = "location")
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java
index c29c3a77..e80d6dca 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepository.java
@@ -130,29 +130,37 @@ public class AwsS3EnvironmentRepository implements EnvironmentRepository, Ordere
private S3ConfigFile getS3ConfigFile(String keyPrefix) {
try {
- final ResponseInputStream responseInputStream = s3Client
- .getObject(GetObjectRequest.builder().bucket(bucketName).key(keyPrefix + ".properties").build());
+ final ResponseInputStream responseInputStream = getObject(keyPrefix + ".properties");
return new PropertyS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
catch (Exception eProperties) {
try {
- final ResponseInputStream responseInputStream = s3Client
- .getObject(GetObjectRequest.builder().bucket(bucketName).key(keyPrefix + ".yml").build());
+ final ResponseInputStream responseInputStream = getObject(keyPrefix + ".yml");
return new YamlS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
- catch (Exception eYaml) {
+ catch (Exception eYml) {
try {
- final ResponseInputStream responseInputStream = s3Client
- .getObject(GetObjectRequest.builder().bucket(bucketName).key(keyPrefix + ".json").build());
- return new JsonS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
+ final ResponseInputStream responseInputStream = getObject(keyPrefix + ".yaml");
+ return new YamlS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
}
- catch (Exception eJson) {
- return null;
+ catch (Exception eYaml) {
+ try {
+ final ResponseInputStream responseInputStream = getObject(
+ keyPrefix + ".json");
+ return new JsonS3ConfigFile(responseInputStream.response().versionId(), responseInputStream);
+ }
+ catch (Exception eJson) {
+ return null;
+ }
}
}
}
}
+ private ResponseInputStream getObject(String key) throws Exception {
+ return s3Client.getObject(GetObjectRequest.builder().bucket(bucketName).key(key).build());
+ }
+
@Override
public Locations getLocations(String application, String profiles, String label) {
String baseLocation = AWS_S3_RESOURCE_SCHEME + bucketName + PATH_SEPARATOR + application;
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/DocumentedConfigObservation.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/DocumentedConfigObservation.java
index ce6bac53..f1e6a348 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/DocumentedConfigObservation.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/DocumentedConfigObservation.java
@@ -18,6 +18,7 @@ package org.springframework.cloud.config.server.environment;
import io.micrometer.common.docs.KeyName;
import io.micrometer.observation.Observation;
+import io.micrometer.observation.ObservationConvention;
import io.micrometer.observation.docs.DocumentedObservation;
enum DocumentedConfigObservation implements DocumentedObservation {
@@ -27,7 +28,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
ENVIRONMENT_REPOSITORY {
@Override
- public Class extends Observation.ObservationConvention extends Observation.Context>> getDefaultConvention() {
+ public Class extends ObservationConvention extends Observation.Context>> getDefaultConvention() {
return ObservationEnvironmentRepositoryObservationConvention.class;
}
@@ -54,7 +55,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
ENVIRONMENT_CLASS {
@Override
- public String getKeyName() {
+ public String asString() {
return "spring.cloud.config.environment.class";
}
},
@@ -64,7 +65,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
PROFILE {
@Override
- public String getKeyName() {
+ public String asString() {
return "spring.cloud.config.environment.profile";
}
},
@@ -74,7 +75,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
LABEL {
@Override
- public String getKeyName() {
+ public String asString() {
return "spring.cloud.config.environment.label";
}
},
@@ -84,7 +85,7 @@ enum DocumentedConfigObservation implements DocumentedObservation {
*/
APPLICATION {
@Override
- public String getKeyName() {
+ public String asString() {
return "spring.cloud.config.environment.application";
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java
index fc043cec..fbf79907 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java
@@ -103,14 +103,12 @@ public class EnvironmentController {
this.acceptEmpty = acceptEmpty;
}
- @GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",
- produces = MediaType.APPLICATION_JSON_VALUE)
+ @GetMapping(path = "/{name}/{profiles:[^\\.]*}", produces = MediaType.APPLICATION_JSON_VALUE)
public Environment defaultLabel(@PathVariable String name, @PathVariable String profiles) {
return getEnvironment(name, profiles, null, false);
}
- @GetMapping(path = "/{name}/{profiles:(?!.*\\b\\.(?:ya?ml|properties|json)\\b).*}",
- produces = EnvironmentMediaType.V2_JSON)
+ @GetMapping(path = "/{name}/{profiles:[^\\.]*}", produces = EnvironmentMediaType.V2_JSON)
public Environment defaultLabelIncludeOrigin(@PathVariable String name, @PathVariable String profiles) {
return getEnvironment(name, profiles, null, true);
}
@@ -464,14 +462,14 @@ public class EnvironmentController {
}
else {
switch (this.propertyKey.charAt(this.currentPos)) {
- case '.':
- this.valueType = NodeType.MAP;
- break;
- case '[':
- this.valueType = NodeType.ARRAY;
- break;
- default:
- throw new IllegalArgumentException("Invalid key: " + this.propertyKey);
+ case '.':
+ this.valueType = NodeType.MAP;
+ break;
+ case '[':
+ this.valueType = NodeType.ARRAY;
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid key: " + this.propertyKey);
}
}
return index;
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java
index 76d8ec0d..c9ad4205 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactory.java
@@ -32,7 +32,6 @@ import java.util.stream.Collectors;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.impl.client.HttpClientBuilder;
-import org.apache.http.impl.client.HttpClients;
import org.eclipse.jgit.transport.http.HttpConnection;
import org.eclipse.jgit.transport.http.apache.HttpClientConnection;
@@ -70,7 +69,16 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
@Override
public HttpConnection create(URL url, Proxy proxy) throws IOException {
- return new HttpClientConnection(url.toString(), null, lookupHttpClientBuilder(url).build());
+ HttpClientBuilder builder = lookupHttpClientBuilder(url);
+ if (builder != null) {
+ return new HttpClientConnection(url.toString(), null, builder.build());
+ }
+ else {
+ /*
+ * No matching builder found: let jGit handle the creation of the HttpClient
+ */
+ return new HttpClientConnection(url.toString());
+ }
}
private void addHttpClient(JGitEnvironmentProperties properties) throws GeneralSecurityException {
@@ -99,7 +107,7 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
if (builderMap.isEmpty()) {
this.log.warn(String.format("No custom http config found for URL: %s", url));
- return HttpClients.custom();
+ return null;
}
if (builderMap.size() > 1) {
/*
@@ -118,7 +126,7 @@ public class HttpClientConfigurableHttpConnectionFactory implements Configurable
"More than one git repo URL template matched URL:"
+ " %s, proxy and skipSslValidation config won't be applied. Matched templates: %s",
url, builderMap.keySet().stream().collect(Collectors.joining(", "))));
- return HttpClients.custom();
+ return null;
}
return new ArrayList<>(builderMap.values()).get(0);
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
index 6206e2c5..2b30adf3 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
@@ -726,7 +726,7 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository
}
List[ branches = command.call();
for (Ref ref : branches) {
- if (ref.getName().endsWith("/" + label)) {
+ if (ref.getName().equals("refs/heads/" + label) || ref.getName().equals("refs/remotes/origin/" + label)) {
return true;
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java
index ac02219c..50760546 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/NativeEnvironmentRepository.java
@@ -270,6 +270,9 @@ public class NativeEnvironmentRepository implements EnvironmentRepository, Searc
locations = new String[] { matcher.group(2) };
}
}
+ name = name.replace("\\", "/"); // change windows path '\' into '/'
+ name = name.replaceAll("\\[(?=\\w:)", "[/"); // change [D:/path] into
+ // [/D:/path]
name = name.replace("applicationConfig: [", "");
name = name.replace("file [", "file:");
name = name.replace("class path resource [", "classpath:/");
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ObservationEnvironmentRepositoryObservationConvention.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ObservationEnvironmentRepositoryObservationConvention.java
index 894c9015..855848bc 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ObservationEnvironmentRepositoryObservationConvention.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/ObservationEnvironmentRepositoryObservationConvention.java
@@ -19,6 +19,7 @@ package org.springframework.cloud.config.server.environment;
import io.micrometer.common.KeyValues;
import io.micrometer.common.docs.KeyName;
import io.micrometer.observation.Observation;
+import io.micrometer.observation.ObservationConvention;
import org.springframework.util.StringUtils;
@@ -29,7 +30,7 @@ import org.springframework.util.StringUtils;
* @since 4.0.0
*/
class ObservationEnvironmentRepositoryObservationConvention
- implements Observation.ObservationConvention {
+ implements ObservationConvention {
@Override
public KeyValues getLowCardinalityKeyValues(ObservationEnvironmentRepositoryContext context) {
@@ -46,7 +47,7 @@ class ObservationEnvironmentRepositoryObservationConvention
private KeyValues appendIfPresent(KeyValues keyValues, KeyName profile, String value) {
if (StringUtils.hasText(value)) {
- keyValues = keyValues.and(profile.of(value));
+ keyValues = keyValues.and(profile.withValue(value));
}
return keyValues;
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultKvAccessStrategyFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultKvAccessStrategyFactory.java
index 75b50154..579ededd 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultKvAccessStrategyFactory.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/VaultKvAccessStrategyFactory.java
@@ -46,12 +46,12 @@ public final class VaultKvAccessStrategyFactory {
public static VaultKvAccessStrategy forVersion(RestOperations rest, String baseUrl, int version, String pathToKey) {
switch (version) {
- case 1:
- return new V1VaultKvAccessStrategy(baseUrl, rest);
- case 2:
- return new V2VaultKvAccessStrategy(baseUrl, pathToKey, rest);
- default:
- throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
+ case 1:
+ return new V1VaultKvAccessStrategy(baseUrl, rest);
+ case 2:
+ return new V2VaultKvAccessStrategy(baseUrl, pathToKey, rest);
+ default:
+ throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/secretmanager/GoogleSecretManagerAccessStrategyFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/secretmanager/GoogleSecretManagerAccessStrategyFactory.java
index 030bf834..2b3c8ee2 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/secretmanager/GoogleSecretManagerAccessStrategyFactory.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/secretmanager/GoogleSecretManagerAccessStrategyFactory.java
@@ -32,16 +32,17 @@ public final class GoogleSecretManagerAccessStrategyFactory {
GoogleSecretManagerEnvironmentProperties properties) {
switch (properties.getVersion()) {
- case 1:
- try {
- return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, properties.getServiceAccount());
- }
- catch (Exception e) {
- throw new RepositoryException("Cannot create service client", e);
- }
- default:
- throw new IllegalArgumentException(
- "No support for given Google Secret manager backend version " + properties.getVersion());
+ case 1:
+ try {
+ return new GoogleSecretManagerV1AccessStrategy(rest, configProvider,
+ properties.getServiceAccount());
+ }
+ catch (Exception e) {
+ throw new RepositoryException("Cannot create service client", e);
+ }
+ default:
+ throw new IllegalArgumentException(
+ "No support for given Google Secret manager backend version " + properties.getVersion());
}
}
@@ -50,11 +51,11 @@ public final class GoogleSecretManagerAccessStrategyFactory {
GoogleSecretManagerEnvironmentProperties properties, SecretManagerServiceClient client) {
switch (properties.getVersion()) {
- case 1:
- return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, client);
- default:
- throw new IllegalArgumentException(
- "No support for given Google Secret manager backend version " + properties.getVersion());
+ case 1:
+ return new GoogleSecretManagerV1AccessStrategy(rest, configProvider, client);
+ default:
+ throw new IllegalArgumentException(
+ "No support for given Google Secret manager backend version " + properties.getVersion());
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java
index 4ed6550c..a1cfdb96 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/vault/SpringVaultEnvironmentRepositoryFactory.java
@@ -61,12 +61,12 @@ public class SpringVaultEnvironmentRepositoryFactory
int version = vaultProperties.getKvVersion();
switch (version) {
- case 1:
- return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_1);
- case 2:
- return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_2);
- default:
- throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
+ case 1:
+ return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_1);
+ case 2:
+ return vaultTemplate.opsForKeyValue(backend, VaultKeyValueOperationsSupport.KeyValueBackend.KV_2);
+ default:
+ throw new IllegalArgumentException("No support for given Vault k/v backend version " + version);
}
}
diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java
index 35195109..bcd310b1 100644
--- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java
+++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/HttpClientSupport.java
@@ -65,6 +65,13 @@ public final class HttpClientSupport {
httpClientBuilder.setDefaultCredentialsProvider(new SystemDefaultCredentialsProvider());
}
+ /*
+ * According to https://git.eclipse.org/c/jgit/jgit.git/commit/?id=
+ * e17bfc96f293744cc5c0cef306e100f53d63bb3d jGit does its own redirect handling
+ * and disables HttpClient's redirect handing.
+ */
+ httpClientBuilder.disableRedirectHandling();
+
int timeout = environmentProperties.getTimeout() * 1000;
return httpClientBuilder.setSSLContext(sslContextBuilder.build()).setDefaultRequestConfig(
RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build());
diff --git a/spring-cloud-config-server/src/main/resources/META-INF/spring.factories b/spring-cloud-config-server/src/main/resources/META-INF/spring.factories
index ed95385a..a2cb54dd 100644
--- a/spring-cloud-config-server/src/main/resources/META-INF/spring.factories
+++ b/spring-cloud-config-server/src/main/resources/META-INF/spring.factories
@@ -1,20 +1,11 @@
# Bootstrap components
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapConfiguration,\
-org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration,\
-org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration,\
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration
# Environment PostProcessor
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.config.server.bootstrap.ConfigServerBootstrapApplicationListener
-# Autoconfiguration
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration,\
-org.springframework.cloud.config.server.config.EncryptionAutoConfiguration,\
-org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration,\
-org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration,\
-org.springframework.cloud.config.server.config.VaultEncryptionAutoConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.config.server.diagnostics.GitUriFailureAnalyzer
diff --git a/spring-cloud-config-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/spring-cloud-config-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..c3634675
--- /dev/null
+++ b/spring-cloud-config-server/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,5 @@
+org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration
+org.springframework.cloud.config.server.config.EncryptionAutoConfiguration
+org.springframework.cloud.config.server.config.DefaultTextEncryptionAutoConfiguration
+org.springframework.cloud.config.server.config.RsaEncryptionAutoConfiguration
+org.springframework.cloud.config.server.config.VaultEncryptionAutoConfiguration
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java
index 30d33a73..4d8cbba4 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/AwsS3EnvironmentRepositoryTests.java
@@ -115,6 +115,15 @@ public class AwsS3EnvironmentRepositoryTests {
@Test
public void findYamlObject() throws UnsupportedEncodingException {
+ setupS3("foo-bar.yaml", yamlContent);
+
+ final Environment env = envRepo.findOne("foo", "bar", null);
+
+ assertExpectedEnvironment(env, "foo", null, null, 1, "bar");
+ }
+
+ @Test
+ public void findYmlObject() throws UnsupportedEncodingException {
setupS3("foo-bar.yml", yamlContent);
final Environment env = envRepo.findOne("foo", "bar", null);
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/EnvironmentControllerTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/EnvironmentControllerTests.java
index ccf15c84..cb2cfff8 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/EnvironmentControllerTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/EnvironmentControllerTests.java
@@ -643,11 +643,11 @@ class EnvironmentControllerTests {
@Test
public void handleEnvironmentException() throws Exception {
- when(EnvironmentControllerTests.this.repository.findOne(eq("exception"), eq("bad_syntax.ext"), any(),
+ when(EnvironmentControllerTests.this.repository.findOne(eq("exception"), eq("bad_syntax"), any(),
eq(false)))
.thenThrow(new FailedToConstructEnvironmentException("Cannot construct",
new RuntimeException("underlier")));
- MvcResult result = this.mvc.perform(MockMvcRequestBuilders.get("/exception/bad_syntax.ext"))
+ MvcResult result = this.mvc.perform(MockMvcRequestBuilders.get("/exception/bad_syntax"))
.andExpect(MockMvcResultMatchers.status().is(500)).andReturn();
assertThat(result.getResponse().getErrorMessage()).isEqualTo("Cannot construct");
}
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactoryTest.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactoryTest.java
index ea2b4f4d..43948763 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactoryTest.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/HttpClientConfigurableHttpConnectionFactoryTest.java
@@ -198,10 +198,8 @@ public class HttpClientConfigurableHttpConnectionFactoryTest {
HttpConnection actualConnection = this.connectionFactory.create(
new URL(properties2.getUri().replace("{placeholder1}", "value1").replace("{placeholder2}", "value2")));
- HttpClientBuilder expectedHttpClientBuilder = this.connectionFactory.httpClientBuildersByUri
- .get(properties2.getUri());
- HttpClientBuilder actualHttpClientBuilder = getActualHttpClientBuilder(actualConnection);
- assertThat(actualHttpClientBuilder).isNotSameAs(expectedHttpClientBuilder);
+ HttpClient actualHttpClient = getActualHttpClient(actualConnection);
+ assertThat(actualHttpClient).isNull();
}
@Test
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java
index c9662493..c0562a13 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java
@@ -230,6 +230,20 @@ public class JGitEnvironmentRepositoryTests {
assertThat(this.repository.getUri()).isEqualTo("git://localhost/foo");
}
+ @Test
+ public void testBranchEndsWithTag() throws IOException {
+ String uri = ConfigServerTestUtils.prepareLocalRepo("branch-with-slash-repo");
+ this.repository.setUri(uri);
+
+ // exists branch "feature/foo"
+ Environment environment = this.repository.findOne("bar", "staging", "feature/foo");
+ assertVersion(environment);
+
+ // try tag "foo"
+ environment = this.repository.findOne("bar", "staging", "foo");
+ assertThat(environment.getPropertySources().get(0).getSource().get("key")).isEqualTo("value from tag");
+ }
+
@Test
public void afterPropertiesSet_CloneOnStartTrue_CloneAndFetchCalled() throws Exception {
Git mockGit = mock(Git.class);
@@ -744,7 +758,7 @@ public class JGitEnvironmentRepositoryTests {
when(checkoutCommand.call()).thenReturn(ref);
when(listBranchCommand.call()).thenReturn(Arrays.asList(branch1Ref));
when(fetchCommand.call()).thenReturn(fetchResult);
- when(branch1Ref.getName()).thenReturn("origin/master");
+ when(branch1Ref.getName()).thenReturn("refs/remotes/origin/master");
when(status.isClean()).thenReturn(true);
JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment,
@@ -1207,12 +1221,12 @@ public class JGitEnvironmentRepositoryTests {
// Mock master branch
Ref mockMasterRef = mock(Ref.class);
repositoryRefsList.add(mockMasterRef);
- when(mockMasterRef.getName()).thenReturn("/master");
+ when(mockMasterRef.getName()).thenReturn("refs/remotes/origin/master");
// Mock release branch.
Ref mockReleaseRef = mock(Ref.class);
repositoryRefsList.add(mockReleaseRef);
- when(mockReleaseRef.getName()).thenReturn("/release");
+ when(mockReleaseRef.getName()).thenReturn("refs/remotes/origin/release");
// Mock calls on list and checkout commands
when(mockListBranchCommand.call()).thenReturn(repositoryRefsList);
@@ -1261,7 +1275,7 @@ public class JGitEnvironmentRepositoryTests {
// Mock master branch
Ref mockMasterRef = mock(Ref.class);
repositoryRefsList.add(mockMasterRef);
- when(mockMasterRef.getName()).thenReturn("/master");
+ when(mockMasterRef.getName()).thenReturn("refs/remotes/origin/master");
// Mock calls on list and checkout commands
when(mockListBranchCommand.call()).thenReturn(repositoryRefsList);
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/RedisEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/RedisEnvironmentRepositoryIntegrationTests.java
index 1dc19b69..e4203eca 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/RedisEnvironmentRepositoryIntegrationTests.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/RedisEnvironmentRepositoryIntegrationTests.java
@@ -49,8 +49,8 @@ public class RedisEnvironmentRepositoryIntegrationTests {
@DynamicPropertySource
static void containerProperties(DynamicPropertyRegistry registry) {
- registry.add("spring.redis.host", redisContainer::getContainerIpAddress);
- registry.add("spring.redis.port", redisContainer::getFirstMappedPort);
+ registry.add("spring.data.redis.host", redisContainer::getHost);
+ registry.add("spring.data.redis.port", redisContainer::getFirstMappedPort);
}
@Test
diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java
index 80cd09a2..a3013632 100644
--- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java
+++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/HttpClientSupportTest.java
@@ -45,7 +45,6 @@ import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
-import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.client.WireMock.verify;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
@@ -77,7 +76,7 @@ public class HttpClientSupportTest {
wireMockProxyServer.start();
wireMockServer.start();
WireMock.configureFor("https", "localhost", wireMockServer.httpsPort());
- stubFor(get("/test/proxy").willReturn(aResponse().withStatus(200)));
+ wireMockServer.stubFor(get("/test/proxy").willReturn(aResponse().withStatus(200)));
JGitEnvironmentProperties properties = new JGitEnvironmentProperties();
Map proxy = new HashMap<>();
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/bar.yml b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/bar.yml
new file mode 100644
index 00000000..5c19df95
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/bar.yml
@@ -0,0 +1 @@
+key: value from master
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/COMMIT_EDITMSG b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/COMMIT_EDITMSG
new file mode 100644
index 00000000..1f7391f9
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/COMMIT_EDITMSG
@@ -0,0 +1 @@
+master
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/HEAD b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/HEAD
new file mode 100644
index 00000000..cb089cd8
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/HEAD
@@ -0,0 +1 @@
+ref: refs/heads/master
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/config b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/config
new file mode 100644
index 00000000..515f4836
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/config
@@ -0,0 +1,5 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/description b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/description
new file mode 100644
index 00000000..498b267a
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/description
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/index b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/index
new file mode 100644
index 00000000..9490d0bb
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/index differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/HEAD b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/HEAD
new file mode 100644
index 00000000..ad8d64c9
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/HEAD
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 7a9804f8901709bdcf794c553805d5bc5188f821 woshikid 1663579538 +0800 commit (initial): tag
+7a9804f8901709bdcf794c553805d5bc5188f821 915bd24aaf815120f2755ef4fc66404f5d37b383 woshikid 1663579645 +0800 commit: branch
+915bd24aaf815120f2755ef4fc66404f5d37b383 08eb9e67a7225c302e3906a63cb9544e619fc804 woshikid 1663579718 +0800 commit: master
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/refs/heads/feature/foo b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/refs/heads/feature/foo
new file mode 100644
index 00000000..cb5b1757
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/refs/heads/feature/foo
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 915bd24aaf815120f2755ef4fc66404f5d37b383 woshikid 1663579678 +0800 branch: Created from master
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/refs/heads/master b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/refs/heads/master
new file mode 100644
index 00000000..ad8d64c9
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/logs/refs/heads/master
@@ -0,0 +1,3 @@
+0000000000000000000000000000000000000000 7a9804f8901709bdcf794c553805d5bc5188f821 woshikid 1663579538 +0800 commit (initial): tag
+7a9804f8901709bdcf794c553805d5bc5188f821 915bd24aaf815120f2755ef4fc66404f5d37b383 woshikid 1663579645 +0800 commit: branch
+915bd24aaf815120f2755ef4fc66404f5d37b383 08eb9e67a7225c302e3906a63cb9544e619fc804 woshikid 1663579718 +0800 commit: master
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/08/eb9e67a7225c302e3906a63cb9544e619fc804 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/08/eb9e67a7225c302e3906a63cb9544e619fc804
new file mode 100644
index 00000000..b0e4abb3
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/08/eb9e67a7225c302e3906a63cb9544e619fc804 differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/0d/706a8f14e7ec2b9abf99c603f3f5467d2d38ff b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/0d/706a8f14e7ec2b9abf99c603f3f5467d2d38ff
new file mode 100644
index 00000000..14556877
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/0d/706a8f14e7ec2b9abf99c603f3f5467d2d38ff differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/54/8298f39d0c5a84a1ada7a2b03ef54aad1fffa2 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/54/8298f39d0c5a84a1ada7a2b03ef54aad1fffa2
new file mode 100644
index 00000000..68285dce
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/54/8298f39d0c5a84a1ada7a2b03ef54aad1fffa2 differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/5c/19df95639519f2286fc6d39182f271ee8c0b6b b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/5c/19df95639519f2286fc6d39182f271ee8c0b6b
new file mode 100644
index 00000000..e39ba7f7
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/5c/19df95639519f2286fc6d39182f271ee8c0b6b differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/6e/067728a52e959f60788121b4046e5b27793e61 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/6e/067728a52e959f60788121b4046e5b27793e61
new file mode 100644
index 00000000..3b5608da
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/6e/067728a52e959f60788121b4046e5b27793e61 differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/7a/9804f8901709bdcf794c553805d5bc5188f821 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/7a/9804f8901709bdcf794c553805d5bc5188f821
new file mode 100644
index 00000000..b9ed165c
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/7a/9804f8901709bdcf794c553805d5bc5188f821
@@ -0,0 +1,2 @@
+xA
+0E]JLR(U&ql@x}swj-fv~]2SBG.EVL.lL$m<
֗TƺnUsʭ^FBlfqot3
\ No newline at end of file
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/91/5bd24aaf815120f2755ef4fc66404f5d37b383 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/91/5bd24aaf815120f2755ef4fc66404f5d37b383
new file mode 100644
index 00000000..39479499
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/91/5bd24aaf815120f2755ef4fc66404f5d37b383 differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/ae/c5d43644133593483b7c243f851606aa2c0128 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/ae/c5d43644133593483b7c243f851606aa2c0128
new file mode 100644
index 00000000..74009400
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/ae/c5d43644133593483b7c243f851606aa2c0128 differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/fa/c65b3a4678430e2b86e3b28510b37c5a7942a7 b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/fa/c65b3a4678430e2b86e3b28510b37c5a7942a7
new file mode 100644
index 00000000..911f6976
Binary files /dev/null and b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/objects/fa/c65b3a4678430e2b86e3b28510b37c5a7942a7 differ
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/heads/feature/foo b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/heads/feature/foo
new file mode 100644
index 00000000..0edf4bff
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/heads/feature/foo
@@ -0,0 +1 @@
+915bd24aaf815120f2755ef4fc66404f5d37b383
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/heads/master b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/heads/master
new file mode 100644
index 00000000..490b6d00
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/heads/master
@@ -0,0 +1 @@
+08eb9e67a7225c302e3906a63cb9544e619fc804
diff --git a/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/tags/foo b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/tags/foo
new file mode 100644
index 00000000..b5ce360d
--- /dev/null
+++ b/spring-cloud-config-server/src/test/resources/branch-with-slash-repo/git/refs/tags/foo
@@ -0,0 +1 @@
+7a9804f8901709bdcf794c553805d5bc5188f821
]