Skip to content

Commit 093e952

Browse files
committed
fix: ignore invalid expressions when parsing config.
1 parent dece4c6 commit 093e952

File tree

4 files changed

+57
-20
lines changed

4 files changed

+57
-20
lines changed

core/config/src/main/java/io/gatehill/imposter/config/util/ConfigUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ object ConfigUtil {
263263
val configFile = configRef.file
264264
try {
265265
val rawContents = configFile.readText()
266-
val parsedContents = ExpressionUtil.eval(rawContents, expressionEvaluators, nullifyUnsupported = false)
266+
val parsedContents = ExpressionUtil.eval(rawContents, expressionEvaluators, onUnsupported = ExpressionUtil.UnsupportedBehaviour.IGNORE)
267267

268268
val config = lookupMapper(configFile).readValue(parsedContents, LightweightConfig::class.java)
269269
config.plugin

core/engine/src/main/java/io/gatehill/imposter/util/PlaceholderUtil.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,6 @@ object PlaceholderUtil {
9393
evaluators: Map<String, ExpressionEvaluator<*>>,
9494
): String {
9595
val context = mapOf(HttpExpressionEvaluator.HTTP_EXCHANGE_KEY to httpExchange)
96-
return ExpressionUtil.eval(input, evaluators, context, queryProvider, nullifyUnsupported = true)
96+
return ExpressionUtil.eval(input, evaluators, context, queryProvider, onUnsupported = ExpressionUtil.UnsupportedBehaviour.NULLIFY)
9797
}
9898
}

core/expression/src/main/java/io/gatehill/imposter/expression/util/ExpressionUtil.kt

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,16 @@ object ExpressionUtil {
6464
*/
6565
private val expressionPattern = Pattern.compile("\\$\\{(.+?)}")
6666

67+
enum class UnsupportedBehaviour {
68+
NULLIFY,
69+
IGNORE,
70+
}
71+
72+
data class MatchResult(
73+
val replace: Boolean,
74+
val replacement: String? = null,
75+
)
76+
6777
/**
6878
* Evaluates an expression in the form:
6979
* ```
@@ -79,7 +89,7 @@ object ExpressionUtil {
7989
evaluators: Map<String, ExpressionEvaluator<*>>,
8090
context: Map<String, Any> = emptyMap(),
8191
queryProvider: QueryProvider? = null,
82-
nullifyUnsupported: Boolean,
92+
onUnsupported: UnsupportedBehaviour,
8393
): String {
8494
val matcher = expressionPattern.matcher(input)
8595
var matched = false
@@ -88,9 +98,14 @@ object ExpressionUtil {
8898
matched = true
8999
val expression = matcher.group(1)
90100
try {
91-
val result = evalSingle(expression, evaluators, context, queryProvider, nullifyUnsupported)
101+
val result = evalSingle(expression, evaluators, context, queryProvider, onUnsupported)
92102
LOGGER.trace("{}={}", expression, result)
93-
matcher.appendReplacement(sb, result)
103+
if (result.replace) {
104+
matcher.appendReplacement(sb, result.replacement)
105+
} else {
106+
matcher.appendReplacement(sb, "")
107+
sb.append(matcher.group(0))
108+
}
94109
} catch (e: Exception) {
95110
throw RuntimeException("Error evaluating expression: $expression", e)
96111
}
@@ -108,24 +123,26 @@ object ExpressionUtil {
108123
evaluators: Map<String, ExpressionEvaluator<*>>,
109124
context: Map<String, Any>,
110125
queryProvider: QueryProvider?,
111-
nullifyUnsupported: Boolean,
112-
): String? {
113-
var result: String? = null
114-
126+
onUnsupported: UnsupportedBehaviour,
127+
): MatchResult {
115128
val evaluator = lookupEvaluator(expression, evaluators)
116129
evaluator?.let {
117-
result = loadAndQuery(expression, context, evaluator, queryProvider) ?: ""
118-
130+
return MatchResult(
131+
replace = true,
132+
replacement = loadAndQuery(expression, context, evaluator, queryProvider) ?: ""
133+
)
119134
} ?: run {
120-
if (nullifyUnsupported) {
121-
LOGGER.warn("Unsupported expression: $expression")
122-
result = ""
123-
} else {
124-
// don't replace; should ignore match
125-
result = "\\\${$expression}"
135+
when (onUnsupported) {
136+
UnsupportedBehaviour.IGNORE -> {
137+
LOGGER.trace("Ignoring unsupported expression: $expression")
138+
return MatchResult(replace = false)
139+
}
140+
UnsupportedBehaviour.NULLIFY -> {
141+
LOGGER.warn("Nullifying unsupported expression: $expression")
142+
return MatchResult(replace = true, replacement = "")
143+
}
126144
}
127145
}
128-
return result
129146
}
130147

131148
private fun lookupEvaluator(

core/expression/src/test/java/io/gatehill/imposter/expression/util/ExpressionUtilTest.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class ExpressionUtilTest {
1616
override fun eval(expression: String, context: Map<String, *>) = null
1717
}
1818
),
19-
nullifyUnsupported = true,
19+
onUnsupported = ExpressionUtil.UnsupportedBehaviour.NULLIFY,
2020
)
2121

2222
assertThat(result, equalTo("fallback"))
@@ -27,8 +27,28 @@ class ExpressionUtilTest {
2727
val result = ExpressionUtil.eval(
2828
input = "\${invalid}",
2929
evaluators = emptyMap(),
30-
nullifyUnsupported = true,
30+
onUnsupported = ExpressionUtil.UnsupportedBehaviour.NULLIFY,
3131
)
3232
assertThat(result, equalTo(""))
3333
}
34+
35+
@Test
36+
fun `ignore invalid expression`() {
37+
val result = ExpressionUtil.eval(
38+
input = "\${some.expression.with:\$inlineDollar}",
39+
evaluators = emptyMap(),
40+
onUnsupported = ExpressionUtil.UnsupportedBehaviour.IGNORE,
41+
)
42+
assertThat(result, equalTo("\${some.expression.with:\$inlineDollar}"))
43+
}
44+
45+
@Test
46+
fun `ignore multiple invalid expressions`() {
47+
val result = ExpressionUtil.eval(
48+
input = "\${some.expression.with:\$inlineDollar} and \${another.expression}",
49+
evaluators = emptyMap(),
50+
onUnsupported = ExpressionUtil.UnsupportedBehaviour.IGNORE,
51+
)
52+
assertThat(result, equalTo("\${some.expression.with:\$inlineDollar} and \${another.expression}"))
53+
}
3454
}

0 commit comments

Comments
 (0)