@marcel91200 / caddy Mirror · read-only / commits / feeb6af4
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 12, 13:15 UTC

httpcaddyfile: Fix expression matcher shortcut in snippets (#6288)

Francis Lavoie committed May 1, 2024 at 07:43 UTC feeb6af40334e6826a57a1a83cc62db672b9b023
3 files changed +73 -9
caddyconfig/caddyfile/lexer.go
+15
@@ -340,6 +340,8 @@ func (l *lexer) finalizeHeredoc(val []rune, marker string) ([]rune, error) {
340 return []rune(out), nil
341 }
342
343 +// Quoted returns true if the token was enclosed in quotes
344 +// (i.e. double quotes, backticks, or heredoc).
345 func (t Token) Quoted() bool {
346 return t.wasQuoted > 0
347 }
@@ -356,6 +358,19 @@ func (t Token) NumLineBreaks() int {
358 return lineBreaks
359 }
360
361 +// Clone returns a deep copy of the token.
362 +func (t Token) Clone() Token {
363 + return Token{
364 + File: t.File,
365 + imports: append([]string{}, t.imports...),
366 + Line: t.Line,
367 + Text: t.Text,
368 + wasQuoted: t.wasQuoted,
369 + heredocMarker: t.heredocMarker,
370 + snippetName: t.snippetName,
371 + }
372 +}
373 +
374 var heredocMarkerRegexp = regexp.MustCompile("^[A-Za-z0-9_-]+$")
375
376 // isNextOnNewLine tests whether t2 is on a different line from t1
caddyconfig/httpcaddyfile/httptype.go
+16 -9
@@ -1282,19 +1282,24 @@ func matcherSetFromMatcherToken(
1282 if tkn.Text == "*" {
1283 // match all requests == no matchers, so nothing to do
1284 return nil, true, nil
1285 - } else if strings.HasPrefix(tkn.Text, "/") {
1286 - // convenient way to specify a single path match
1285 + }
1286 +
1287 + // convenient way to specify a single path match
1288 + if strings.HasPrefix(tkn.Text, "/") {
1289 return caddy.ModuleMap{
1290 "path": caddyconfig.JSON(caddyhttp.MatchPath{tkn.Text}, warnings),
1291 }, true, nil
1290 - } else if strings.HasPrefix(tkn.Text, matcherPrefix) {
1291 - // pre-defined matcher
1292 + }
1293 +
1294 + // pre-defined matcher
1295 + if strings.HasPrefix(tkn.Text, matcherPrefix) {
1296 m, ok := matcherDefs[tkn.Text]
1297 if !ok {
1298 return nil, false, fmt.Errorf("unrecognized matcher name: %+v", tkn.Text)
1299 }
1300 return m, true, nil
1301 }
1302 +
1303 return nil, false, nil
1304 }
1305
@@ -1430,11 +1435,13 @@ func parseMatcherDefinitions(d *caddyfile.Dispenser, matchers map[string]caddy.M
1435 if d.NextArg() {
1436 if d.Token().Quoted() {
1437 // since it was missing the matcher name, we insert a token
1433 - // in front of the expression token itself
1434 - err := makeMatcher("expression", []caddyfile.Token{
1435 - {Text: "expression", File: d.File(), Line: d.Line()},
1436 - d.Token(),
1437 - })
1438 + // in front of the expression token itself; we use Clone() to
1439 + // make the new token to keep the same the import location as
1440 + // the next token, if this is within a snippet or imported file.
1441 + // see https://github.com/caddyserver/caddy/issues/6287
1442 + expressionToken := d.Token().Clone()
1443 + expressionToken.Text = "expression"
1444 + err := makeMatcher("expression", []caddyfile.Token{expressionToken, d.Token()})
1445 if err != nil {
1446 return err
1447 }
caddytest/integration/caddyfile_adapt/expression_quotes.caddyfiletest
+42
@@ -1,3 +1,7 @@
1 +(snippet) {
2 + @g `{http.error.status_code} == 404`
3 +}
4 +
5 example.com
6
7 @a expression {http.error.status_code} == 400
@@ -14,6 +18,12 @@ abort @d
18
19 @e expression `{http.error.status_code} == 404`
20 abort @e
21 +
22 +@f `{http.error.status_code} == 404`
23 +abort @f
24 +
25 +import snippet
26 +abort @g
27 ----------
28 {
29 "apps": {
@@ -106,6 +116,38 @@ abort @e
116 }
117 }
118 ]
119 + },
120 + {
121 + "handle": [
122 + {
123 + "abort": true,
124 + "handler": "static_response"
125 + }
126 + ],
127 + "match": [
128 + {
129 + "expression": {
130 + "expr": "{http.error.status_code} == 404",
131 + "name": "f"
132 + }
133 + }
134 + ]
135 + },
136 + {
137 + "handle": [
138 + {
139 + "abort": true,
140 + "handler": "static_response"
141 + }
142 + ],
143 + "match": [
144 + {
145 + "expression": {
146 + "expr": "{http.error.status_code} == 404",
147 + "name": "g"
148 + }
149 + }
150 + ]
151 }
152 ]
153 }