From 35d176e56f99f70cbce5f841c3963dcd28c664cd Mon Sep 17 00:00:00 2001 From: Larry Ogrodnek Date: Mon, 17 Sep 2018 09:36:50 -0400 Subject: [PATCH] #974 remove one or two escapes for supporting JSON (#982) Hi. This is an attempt to fix #974 (cc @ryanjbaxter ) As mentioned previously in the ticket, the original code tries to mask out escaped variables (i.e. `\${hello}`) before performing replacement, and then finally removing the escapes before returning. This works fine for .yaml or .properties, but not for JSON. The jackson serialization that happens before the property resolution ends up adding an extra `\` (so that the JSON is well-formed) [EnvironmentController.labelledJsonPropertes](https://github.com/spring-cloud/spring-cloud-config/blob/master/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java#L169). I've updated the `resolverPlaceholders` to accept one or two escapes (`\` or `\\`). I realize this will now treat `\\` as an escape in yml or properties, which may be unintended, but seems unlikely. An alternative might be to add a flag to this method to indicate whether or not to allow double escape, and updating the `labelledJson` method to pass the flag? I'm open to any feedback on this approach or another. Thanks! --- .../support/EnvironmentPropertySource.java | 10 +++++++--- .../support/EnvironmentPropertySourceTest.java | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/EnvironmentPropertySourceTest.java diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentPropertySource.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentPropertySource.java index 00a47c28..d1e91bf8 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentPropertySource.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/support/EnvironmentPropertySource.java @@ -1,6 +1,7 @@ package org.springframework.cloud.config.server.support; import java.util.Map; +import java.util.regex.Pattern; import org.springframework.cloud.config.environment.Environment; import org.springframework.core.env.PropertySource; @@ -22,11 +23,14 @@ public class EnvironmentPropertySource extends PropertySource { return standardEnvironment; } + // "\${" (from text) or "\\${" from JSON to signal escaped placeholder + private static final Pattern ESCAPED_PLACEHOLDERS = Pattern.compile("[\\\\]{1,2}\\$\\{"); + public static String resolvePlaceholders(StandardEnvironment preparedEnvironment, String text) { - // Mask out escaped placeholders - text = text.replace("\\${", "$_{"); - return preparedEnvironment.resolvePlaceholders(text).replace("$_{", "${"); + // Mask out escaped placeholders + text = ESCAPED_PLACEHOLDERS.matcher(text).replaceAll("\\$_{"); + return preparedEnvironment.resolvePlaceholders(text).replace("$_{", "${"); } public EnvironmentPropertySource(Environment sources) { diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/EnvironmentPropertySourceTest.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/EnvironmentPropertySourceTest.java new file mode 100644 index 00000000..58cc5211 --- /dev/null +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/support/EnvironmentPropertySourceTest.java @@ -0,0 +1,18 @@ +package org.springframework.cloud.config.server.support; + +import static org.junit.Assert.assertEquals; +import static org.springframework.cloud.config.server.support.EnvironmentPropertySource.resolvePlaceholders; + +import org.junit.Test; +import org.springframework.core.env.StandardEnvironment; + +public class EnvironmentPropertySourceTest { + private final StandardEnvironment env = new StandardEnvironment(); + + @Test + public void testEscapedPlaceholdersRemoved() { + assertEquals("${abc}", resolvePlaceholders(env, "\\${abc}")); + // JSON generated from jackson will be double escaped + assertEquals("${abc}", resolvePlaceholders(env, "\\\\${abc}")); + } +}