diff options
author | Francis Lavoie <[email protected]> | 2024-05-01 07:43:05 -0400 |
---|---|---|
committer | GitHub <[email protected]> | 2024-05-01 07:43:05 -0400 |
commit | feeb6af40334e6826a57a1a83cc62db672b9b023 (patch) | |
tree | 69f5366af40fd6017ff58789bc33bb7350c7632c | |
parent | d129ae6aec6af2182217ee8a235f4df8cd2bbfde (diff) | |
download | caddy-feeb6af40334e6826a57a1a83cc62db672b9b023.tar.gz caddy-feeb6af40334e6826a57a1a83cc62db672b9b023.zip |
httpcaddyfile: Fix expression matcher shortcut in snippets (#6288)
-rw-r--r-- | caddyconfig/caddyfile/lexer.go | 15 | ||||
-rw-r--r-- | caddyconfig/httpcaddyfile/httptype.go | 25 | ||||
-rw-r--r-- | caddytest/integration/caddyfile_adapt/expression_quotes.caddyfiletest | 42 |
3 files changed, 73 insertions, 9 deletions
diff --git a/caddyconfig/caddyfile/lexer.go b/caddyconfig/caddyfile/lexer.go index 4db63749b..9b523f397 100644 --- a/caddyconfig/caddyfile/lexer.go +++ b/caddyconfig/caddyfile/lexer.go @@ -340,6 +340,8 @@ func (l *lexer) finalizeHeredoc(val []rune, marker string) ([]rune, error) { return []rune(out), nil } +// Quoted returns true if the token was enclosed in quotes +// (i.e. double quotes, backticks, or heredoc). func (t Token) Quoted() bool { return t.wasQuoted > 0 } @@ -356,6 +358,19 @@ func (t Token) NumLineBreaks() int { return lineBreaks } +// Clone returns a deep copy of the token. +func (t Token) Clone() Token { + return Token{ + File: t.File, + imports: append([]string{}, t.imports...), + Line: t.Line, + Text: t.Text, + wasQuoted: t.wasQuoted, + heredocMarker: t.heredocMarker, + snippetName: t.snippetName, + } +} + var heredocMarkerRegexp = regexp.MustCompile("^[A-Za-z0-9_-]+$") // isNextOnNewLine tests whether t2 is on a different line from t1 diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go index 0d831403b..8e7d21fa0 100644 --- a/caddyconfig/httpcaddyfile/httptype.go +++ b/caddyconfig/httpcaddyfile/httptype.go @@ -1282,19 +1282,24 @@ func matcherSetFromMatcherToken( if tkn.Text == "*" { // match all requests == no matchers, so nothing to do return nil, true, nil - } else if strings.HasPrefix(tkn.Text, "/") { - // convenient way to specify a single path match + } + + // convenient way to specify a single path match + if strings.HasPrefix(tkn.Text, "/") { return caddy.ModuleMap{ "path": caddyconfig.JSON(caddyhttp.MatchPath{tkn.Text}, warnings), }, true, nil - } else if strings.HasPrefix(tkn.Text, matcherPrefix) { - // pre-defined matcher + } + + // pre-defined matcher + if strings.HasPrefix(tkn.Text, matcherPrefix) { m, ok := matcherDefs[tkn.Text] if !ok { return nil, false, fmt.Errorf("unrecognized matcher name: %+v", tkn.Text) } return m, true, nil } + return nil, false, nil } @@ -1430,11 +1435,13 @@ func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.M if d.NextArg() { if d.Token().Quoted() { // since it was missing the matcher name, we insert a token - // in front of the expression token itself - err := makeMatcher("expression", []caddyfile.Token{ - {Text: "expression", File: d.File(), Line: d.Line()}, - d.Token(), - }) + // in front of the expression token itself; we use Clone() to + // make the new token to keep the same the import location as + // the next token, if this is within a snippet or imported file. + // see https://github.com/caddyserver/caddy/issues/6287 + expressionToken := d.Token().Clone() + expressionToken.Text = "expression" + err := makeMatcher("expression", []caddyfile.Token{expressionToken, d.Token()}) if err != nil { return err } diff --git a/caddytest/integration/caddyfile_adapt/expression_quotes.caddyfiletest b/caddytest/integration/caddyfile_adapt/expression_quotes.caddyfiletest index e0f5bd715..4bc47a3dc 100644 --- a/caddytest/integration/caddyfile_adapt/expression_quotes.caddyfiletest +++ b/caddytest/integration/caddyfile_adapt/expression_quotes.caddyfiletest @@ -1,3 +1,7 @@ +(snippet) { + @g `{http.error.status_code} == 404` +} + example.com @a expression {http.error.status_code} == 400 @@ -14,6 +18,12 @@ abort @d @e expression `{http.error.status_code} == 404` abort @e + +@f `{http.error.status_code} == 404` +abort @f + +import snippet +abort @g ---------- { "apps": { @@ -106,6 +116,38 @@ abort @e } } ] + }, + { + "handle": [ + { + "abort": true, + "handler": "static_response" + } + ], + "match": [ + { + "expression": { + "expr": "{http.error.status_code} == 404", + "name": "f" + } + } + ] + }, + { + "handle": [ + { + "abort": true, + "handler": "static_response" + } + ], + "match": [ + { + "expression": { + "expr": "{http.error.status_code} == 404", + "name": "g" + } + } + ] } ] } |