@marcel91200 / caddy Mirror · read-only / commits / df65455b
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 13:30 UTC

caddyhttp: Sync placeholder expansion in `vars` and `vars_regexp` (#7573)

* vars: Expand placeholders in custom variables like in `vars_regexp` * vars: Reuse variables inside match loops

vnxme committed Mar 17, 2026 at 22:08 UTC df65455b1f0d230a34d4bd7111213fe6917abe98
1 file changed +37 -22
modules/caddyhttp/vars.go
+37 -22
@@ -181,33 +181,46 @@ func (m VarsMatcher) MatchWithError(r *http.Request) (bool, error) {
181 vars := r.Context().Value(VarsCtxKey).(map[string]any)
182 repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
183
184 + var fromPlaceholder bool
185 + var matcherValExpanded, valExpanded, varStr, v string
186 + var varValue any
187 for key, vals := range m {
185 - var varValue any
188 if strings.HasPrefix(key, "{") &&
189 strings.HasSuffix(key, "}") &&
190 strings.Count(key, "{") == 1 {
191 varValue, _ = repl.Get(strings.Trim(key, "{}"))
192 + fromPlaceholder = true
193 } else {
194 varValue = vars[key]
195 + fromPlaceholder = false
196 + }
197 +
198 + switch vv := varValue.(type) {
199 + case string:
200 + varStr = vv
201 + case fmt.Stringer:
202 + varStr = vv.String()
203 + case error:
204 + varStr = vv.Error()
205 + case nil:
206 + varStr = ""
207 + default:
208 + varStr = fmt.Sprintf("%v", vv)
209 + }
210 +
211 + // Only expand placeholders in values from literal variable names
212 + // (e.g. map outputs). Values resolved from placeholder keys are
213 + // already final and must not be re-expanded, as that would allow
214 + // user input like {env.SECRET} to be evaluated.
215 + valExpanded = varStr
216 + if !fromPlaceholder {
217 + valExpanded = repl.ReplaceAll(varStr, "")
218 }
219
220 // see if any of the values given in the matcher match the actual value
195 - for _, v := range vals {
196 - matcherValExpanded := repl.ReplaceAll(v, "")
197 - var varStr string
198 - switch vv := varValue.(type) {
199 - case string:
200 - varStr = vv
201 - case fmt.Stringer:
202 - varStr = vv.String()
203 - case error:
204 - varStr = vv.Error()
205 - case nil:
206 - varStr = ""
207 - default:
208 - varStr = fmt.Sprintf("%v", vv)
209 - }
210 - if varStr == matcherValExpanded {
221 + for _, v = range vals {
222 + matcherValExpanded = repl.ReplaceAll(v, "")
223 + if valExpanded == matcherValExpanded {
224 return true, nil
225 }
226 }
@@ -310,9 +323,11 @@ func (m MatchVarsRE) Match(r *http.Request) bool {
323 func (m MatchVarsRE) MatchWithError(r *http.Request) (bool, error) {
324 vars := r.Context().Value(VarsCtxKey).(map[string]any)
325 repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer)
326 +
327 + var fromPlaceholder, match bool
328 + var valExpanded, varStr string
329 + var varValue any
330 for key, val := range m {
314 - var varValue any
315 - var fromPlaceholder bool
331 if strings.HasPrefix(key, "{") &&
332 strings.HasSuffix(key, "}") &&
333 strings.Count(key, "{") == 1 {
@@ -320,9 +335,9 @@ func (m MatchVarsRE) MatchWithError(r *http.Request) (bool, error) {
335 fromPlaceholder = true
336 } else {
337 varValue = vars[key]
338 + fromPlaceholder = false
339 }
340
325 - var varStr string
341 switch vv := varValue.(type) {
342 case string:
343 varStr = vv
@@ -340,11 +355,11 @@ func (m MatchVarsRE) MatchWithError(r *http.Request) (bool, error) {
355 // (e.g. map outputs). Values resolved from placeholder keys are
356 // already final and must not be re-expanded, as that would allow
357 // user input like {env.SECRET} to be evaluated.
343 - valExpanded := varStr
358 + valExpanded = varStr
359 if !fromPlaceholder {
360 valExpanded = repl.ReplaceAll(varStr, "")
361 }
347 - if match := val.Match(valExpanded, repl); match {
362 + if match = val.Match(valExpanded, repl); match {
363 return match, nil
364 }
365 }