@marcel91200 / caddy Mirror · read-only / commits / cee4441c
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 13, 01:45 UTC

caddyfile: Do not replace import tokens if they are part of a snippet (#5539)

* fix variadic placeholder in imported file which also imports * fix tests. * skip replacing args when imported token may be part of a snippet

WeidiDeng committed May 23, 2023 at 05:36 UTC cee4441cb1d485b38d728168a315cda5641d84fb
5 files changed +99 -5
caddyconfig/caddyfile/parse.go
+45 -5
@@ -214,7 +214,7 @@ func (p *parser) addresses() error {
214
215 // special case: import directive replaces tokens during parse-time
216 if tkn == "import" && p.isNewLine() {
217 - err := p.doImport()
217 + err := p.doImport(0)
218 if err != nil {
219 return err
220 }
@@ -314,7 +314,7 @@ func (p *parser) directives() error {
314
315 // special case: import directive replaces tokens during parse-time
316 if p.Val() == "import" {
317 - err := p.doImport()
317 + err := p.doImport(1)
318 if err != nil {
319 return err
320 }
@@ -340,7 +340,7 @@ func (p *parser) directives() error {
340 // is on the token before where the import directive was. In
341 // other words, call Next() to access the first token that was
342 // imported.
343 -func (p *parser) doImport() error {
343 +func (p *parser) doImport(nesting int) error {
344 // syntax checks
345 if !p.NextArg() {
346 return p.ArgErr()
@@ -443,10 +443,16 @@ func (p *parser) doImport() error {
443 // copy the tokens so we don't overwrite p.definedSnippets
444 tokensCopy := make([]Token, 0, len(importedTokens))
445
446 + var (
447 + maybeSnippet bool
448 + maybeSnippetId bool
449 + index int
450 + )
451 +
452 // run the argument replacer on the tokens
453 // golang for range slice return a copy of value
454 // similarly, append also copy value
449 - for _, token := range importedTokens {
455 + for i, token := range importedTokens {
456 // set the token's file to refer to import directive line number and snippet name
457 if token.snippetName != "" {
458 token.updateFile(fmt.Sprintf("%s:%d (import %s)", token.File, p.Line(), token.snippetName))
@@ -454,6 +460,40 @@ func (p *parser) doImport() error {
460 token.updateFile(fmt.Sprintf("%s:%d (import)", token.File, p.Line()))
461 }
462
463 + // naive way of determine snippets, as snippets definition can only follow name + block
464 + // format, won't check for nesting correctness or any other error, that's what parser does.
465 + if !maybeSnippet && nesting == 0 {
466 + // first of the line
467 + if i == 0 || importedTokens[i-1].originalFile() != token.originalFile() || importedTokens[i-1].Line+importedTokens[i-1].NumLineBreaks() < token.Line {
468 + index = 0
469 + } else {
470 + index++
471 + }
472 +
473 + if index == 0 && len(token.Text) >= 3 && strings.HasPrefix(token.Text, "(") && strings.HasSuffix(token.Text, ")") {
474 + maybeSnippetId = true
475 + }
476 + }
477 +
478 + switch token.Text {
479 + case "{":
480 + nesting++
481 + if index == 1 && maybeSnippetId && nesting == 1 {
482 + maybeSnippet = true
483 + maybeSnippetId = false
484 + }
485 + case "}":
486 + nesting--
487 + if nesting == 0 && maybeSnippet {
488 + maybeSnippet = false
489 + }
490 + }
491 +
492 + if maybeSnippet {
493 + tokensCopy = append(tokensCopy, token)
494 + continue
495 + }
496 +
497 foundVariadic, startIndex, endIndex := parseVariadic(token, len(args))
498 if foundVariadic {
499 for _, arg := range args[startIndex:endIndex] {
@@ -553,7 +593,7 @@ func (p *parser) directive() error {
593 } else if p.Val() == "}" && p.nesting == 0 {
594 return p.Err("Unexpected '}' because no matching opening brace")
595 } else if p.Val() == "import" && p.isNewLine() {
556 - if err := p.doImport(); err != nil {
596 + if err := p.doImport(1); err != nil {
597 return err
598 }
599 p.cursor-- // cursor is advanced when we continue, so roll back one more
caddyconfig/httpcaddyfile/builtins_test.go
+21
@@ -243,6 +243,27 @@ func TestImportErrorLine(t *testing.T) {
243 return err != nil && strings.Contains(err.Error(), "Caddyfile:5 (import t1):2")
244 },
245 },
246 + {
247 + input: `
248 + import testdata/import_variadic_snippet.txt
249 + :8080 {
250 + import t1 true
251 + }`,
252 + errorFunc: func(err error) bool {
253 + return err == nil
254 + },
255 + },
256 + {
257 + input: `
258 + import testdata/import_variadic_with_import.txt
259 + :8080 {
260 + import t1 true
261 + import t2 true
262 + }`,
263 + errorFunc: func(err error) bool {
264 + return err == nil
265 + },
266 + },
267 } {
268 adapter := caddyfile.Adapter{
269 ServerType: ServerType{},
caddyconfig/httpcaddyfile/testdata/import_variadic.txt new
+9
@@ -0,0 +1,9 @@
1 +(t2) {
2 + respond 200 {
3 + body {args[:]}
4 + }
5 +}
6 +
7 +:8082 {
8 + import t2 false
9 +}
\ No newline at end of file
caddyconfig/httpcaddyfile/testdata/import_variadic_snippet.txt new
+9
@@ -0,0 +1,9 @@
1 +(t1) {
2 + respond 200 {
3 + body {args[:]}
4 + }
5 +}
6 +
7 +:8081 {
8 + import t1 false
9 +}
\ No newline at end of file
caddyconfig/httpcaddyfile/testdata/import_variadic_with_import.txt new
+15
@@ -0,0 +1,15 @@
1 +(t1) {
2 + respond 200 {
3 + body {args[:]}
4 + }
5 +}
6 +
7 +:8081 {
8 + import t1 false
9 +}
10 +
11 +import import_variadic.txt
12 +
13 +:8083 {
14 + import t2 true
15 +}
\ No newline at end of file