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