Skip to content

Commit

Permalink
Support default values in placeholders
Browse files Browse the repository at this point in the history
Support variable expansion also in placeholders, like in
`{unsetPlaceholder:default value}`. Implemented similarly to caddyserver#3682,
which provided defaults for environment variable expansion.

Closes caddyserver#1793.

Signed-off-by: Jens Erat <jens.erat@mercedes-benz.com>
  • Loading branch information
JensErat committed Feb 7, 2023
1 parent c77a6be commit c4b6f23
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 16 deletions.
40 changes: 27 additions & 13 deletions replacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,27 +188,39 @@ scan:
sb.WriteString(input[lastWriteCursor:i])

// trim opening bracket
key := input[i+1 : end]
keyString := input[i+1 : end]

// split the string into a key and an optional default
keyParts := strings.SplitN(string(keyString), varDefaultDelimiter, 2)

// try to get a value for this key, handle empty values accordingly
val, found := r.Get(key)
val, found := r.Get(keyParts[0])
if !found {
// placeholder is unknown (unrecognized); handle accordingly
if errOnUnknown {
return "", fmt.Errorf("unrecognized placeholder %s%s%s",
string(phOpen), key, string(phClose))
} else if !treatUnknownAsEmpty {
// if treatUnknownAsEmpty is true, we'll handle an empty
// val later; so only continue otherwise
lastWriteCursor = i
continue
// replace with variable default, if one is defined
if len(keyParts) == 2 {
val = keyParts[1]
if val == "" {
return "", fmt.Errorf("evaluated placeholder %s%s%s and default are empty",
string(phOpen), keyString, string(phClose))
}
} else {
// placeholder is unknown (unrecognized); handle accordingly
if errOnUnknown {
return "", fmt.Errorf("unrecognized placeholder %s%s%s",
string(phOpen), keyParts[0], string(phClose))
} else if !treatUnknownAsEmpty {
// if treatUnknownAsEmpty is true, we'll handle an empty
// val later; so only continue otherwise
lastWriteCursor = i
continue
}
}
}

// apply any transformations
if f != nil {
var err error
val, err = f(key, val)
val, err = f(keyParts[0], val)
if err != nil {
return "", err
}
Expand All @@ -222,7 +234,7 @@ scan:
if valStr == "" {
if errOnEmpty {
return "", fmt.Errorf("evaluated placeholder %s%s%s is empty",
string(phOpen), key, string(phClose))
string(phOpen), keyParts[0], string(phClose))
} else if empty != "" {
sb.WriteString(empty)
}
Expand Down Expand Up @@ -345,3 +357,5 @@ var nowFunc = time.Now
const ReplacerCtxKey CtxKey = "replacer"

const phOpen, phClose, phEscape = '{', '}', '\\'

const varDefaultDelimiter = ":"
25 changes: 22 additions & 3 deletions replacer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,13 @@ func TestReplacer(t *testing.T) {
input: `\{\}`,
expect: `{}`,
},
{
{ // TODO currently failing, we might split using a regex or check last character of actual placeholder key not to be a backslash
input: `{"json"\: "object"}`,
expect: ``,
},
{ // TODO currently not failing, is this expected behavior? I guess users would just need to escape the colon in future, see test above
input: `{"json": "object"}`,
expect: "",
expect: ` "object"`, // placeholder defaulting happened
},
{
input: `\{"json": "object"}`,
Expand Down Expand Up @@ -123,7 +127,7 @@ func TestReplacer(t *testing.T) {
input: `{{}`,
expect: "",
},
{
{ // TODO currently failing, is this a parser bug? not a finished placeholder sequence
input: `{"json": "object"\}`,
expect: "",
},
Expand Down Expand Up @@ -294,6 +298,21 @@ func TestReplacerReplaceKnown(t *testing.T) {
testInput: "{test1} {nope} {1} ",
expected: "val1 {nope} test-123 ",
},
{
// test with default
testInput: "{nope} {nope:default} {test1:default}",
expected: "{nope} default val1",
},
{
// test with empty default
testInput: "{nope:}",
expected: "",
},
{
// should not chain variable expands
testInput: "{nope:$test1}",
expected: "$test1",
},
} {
actual := rep.ReplaceKnown(tc.testInput, "EMPTY")

Expand Down

0 comments on commit c4b6f23

Please sign in to comment.