Describe the bug If a client app, e.g. "TestApp" has a TestApp.properties file containing properties such as:

Root=${env:LOCAL_Root/-c:/vueroot}

And then if you call {CONFIG-SERVER-URL}/dev/TestApp-dev.properties, the Root property is returned as:

Root: LOCAL_Root/-c:/vueroot

I'm not sure what the expected behavior is here, or what rule is being applied to modify it as such. There may not be a defect, but what I would expect is that it would return the value exactly as defined in the .properties file:

Root=${env:LOCAL_Root/-c:/vueroot}

I did not find any documentation that would indicate this property is utilizing some config server feature, and thus would explain the observed behavior.

Note that this also occurs if you use the "yml" or "json" format instead of "properties" in the request.

Sample Here is a project that demonstrates the issues. The "TestApp.properties" file is under the resources/config folder. ResolvePropertiesConfigServer2.zip

  1. Unzip the app.
  2. Run the app as usual
  3. Send request: http://localhost:8080/dev/TestApp-dev.properties, http://localhost:8080/dev/TestApp-dev.yml, or http://localhost:8080/dev/TestApp-dev.json

Observe the manipulated value of the "Root" property.

Comment From: ryanjbaxter

I think what is happening is exactly what is documented here

After a resource is located, placeholders in the normal format (${…​}) are resolved by using the effective Environment for the supplied application name, profile, and label. In this way, the resource endpoint is tightly integrated with the environment endpoints.

https://github.com/spring-cloud/spring-cloud-config/blob/main/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/EnvironmentController.java#L168

So you have two options.

  1. You can escape the property so the placeholder is not resolved Root=\\${env:LOCAL_Root/-c:/vueroot}
  2. You can pass a query parameter to disable resolving placeholders http://localhost:8080/dev/TestApp-dev.properties?resolvePlaceholders==false

Comment From: spring-cloud-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

Comment From: spring-cloud-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

Comment From: marnee01

I looked at this more closely after this was closed.

In the documentation you linked and in the code you referenced, I don't see an explanation of why the ConfigServer is lopping off the part before the slash inside the value. The linked documentation doesn't seem to discuss anything regards to having special characters within property values. In normal cases, if the referenced property is not resolved, the value is returned as-is.

In the test project I sent, I updated the contents of TestApp.properties to contain:

Root1=${env:LOCAL_Root/-c:/vueroot}
Root2=${env_LOCAL_Root/-c:/vueroot}
Root3=${prefix/suffix}
Root4=${NON_EXISTENT_PROPERTY}

I would expect the values returned as-is:

Root1: ${env:LOCAL_Root/-c:/vueroot}
Root2: ${env_LOCAL_Root/-c:/vueroot}
Root3: ${prefix/suffix}
Root4: ${NON_EXISTENT_PROPERTY}

But it "resolves" the tokens for the first two, and not the last two. I can't discern a rule here:

Root1: LOCAL_Root/-c:/vueroot
Root2: /vueroot
Root3: ${prefix/suffix}
Root4: ${NON_EXISTENT_PROPERTY}

Seems to be related to the colon, but I don't know what the syntax is for these or what it is trying to accomplish.

Comment From: ryanjbaxter

Ultimately what we end up calling is PropertyResolver.resolvePlaceholders. As you can see from the docs unresolved properties are just returned as is. Root1 and Root2 are "resolved" because the : acts as an or. So either we either resolve env in the case of Root1 or return LOCAL_Root/-c:/vueroot or we resolve env_LOCAL_Root/-c or retur. vuewroot in the case of Root2.

Comment From: marnee01

@ryanjbaxter Where is it documented that : acts as an or?

Comment From: ryanjbaxter

I should have said : allows you to specify a default value.

But in any case this is the best reference I could find on that behavior https://docs.spring.io/spring-framework/reference/core/beans/annotation-config/value-annotations.html

Comment From: marnee01

Ah, yes, makes sense. Thanks for the info @ryanjbaxter !