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, 18:15 UTC
httpcaddyfile: Rewrite `root` and `rewrite` parsing to allow omitting matcher (#5844)
Francis Lavoie committed
Jan 15, 2024 at 11:57 UTC
5e2f1b5ced5e7153f9748477612cf46188470ca7
4 files changed
+296
-12
caddyconfig/httpcaddyfile/builtins.go
+36
-9
@@ -41,7 +41,7 @@ func init() {
41
RegisterDirective("bind", parseBind)
42
RegisterDirective("tls", parseTLS)
43
RegisterHandlerDirective("fs", parseFilesystem)
44
- RegisterHandlerDirective("root", parseRoot)
44
+ RegisterDirective("root", parseRoot)
45
RegisterHandlerDirective("vars", parseVars)
46
RegisterHandlerDirective("redir", parseRedir)
47
RegisterHandlerDirective("respond", parseRespond)
@@ -645,18 +645,45 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
645
// parseRoot parses the root directive. Syntax:
646
//
647
// root [<matcher>] <path>
648
-func parseRoot(h Helper) (caddyhttp.MiddlewareHandler, error) {
649
- var root string
650
- for h.Next() {
648
+func parseRoot(h Helper) ([]ConfigValue, error) {
649
+ // consume directive name
650
+ if !h.NextArg() {
651
+ return nil, h.ArgErr()
652
+ }
653
+
654
+ // count the tokens to determine what to do
655
+ argsCount := h.CountRemainingArgs()
656
+ if argsCount == 0 {
657
+ return nil, h.Errf("too few arguments; must have at least a root path")
658
+ }
659
+ if argsCount > 2 {
660
+ return nil, h.Errf("too many arguments; should only be a matcher and a path")
661
+ }
662
+
663
+ // with only one arg, assume it's a root path with no matcher token
664
+ if argsCount == 1 {
665
if !h.NextArg() {
666
return nil, h.ArgErr()
667
}
654
- root = h.Val()
655
- if h.NextArg() {
656
- return nil, h.ArgErr()
657
- }
668
+ return h.NewRoute(nil, caddyhttp.VarsMiddleware{"root": h.Val()}), nil
669
+ }
670
+
671
+ // parse the matcher token into a matcher set
672
+ userMatcherSet, err := h.ExtractMatcherSet()
673
+ if err != nil {
674
+ return nil, err
675
+ }
676
+
677
+ // consume directive name, again, because extracting matcher does a reset
678
+ if !h.NextArg() {
679
+ return nil, h.ArgErr()
680
+ }
681
+ // advance to the root path
682
+ if !h.NextArg() {
683
+ return nil, h.ArgErr()
684
}
659
- return caddyhttp.VarsMiddleware{"root": root}, nil
685
+ // make the route with the matcher
686
+ return h.NewRoute(userMatcherSet, caddyhttp.VarsMiddleware{"root": h.Val()}), nil
687
}
688
689
// parseFilesystem parses the fs directive. Syntax:
caddytest/integration/caddyfile_adapt/rewrite_directive_permutations.txt
new
+112
@@ -0,0 +1,112 @@
1
+:8080
2
+
3
+# With explicit wildcard matcher
4
+route {
5
+ rewrite * /a
6
+}
7
+
8
+# With path matcher
9
+route {
10
+ rewrite /path /b
11
+}
12
+
13
+# With named matcher
14
+route {
15
+ @named method GET
16
+ rewrite @named /c
17
+}
18
+
19
+# With no matcher, assumed to be wildcard
20
+route {
21
+ rewrite /d
22
+}
23
+----------
24
+{
25
+ "apps": {
26
+ "http": {
27
+ "servers": {
28
+ "srv0": {
29
+ "listen": [
30
+ ":8080"
31
+ ],
32
+ "routes": [
33
+ {
34
+ "handle": [
35
+ {
36
+ "handler": "subroute",
37
+ "routes": [
38
+ {
39
+ "group": "group0",
40
+ "handle": [
41
+ {
42
+ "handler": "rewrite",
43
+ "uri": "/a"
44
+ }
45
+ ]
46
+ }
47
+ ]
48
+ },
49
+ {
50
+ "handler": "subroute",
51
+ "routes": [
52
+ {
53
+ "group": "group1",
54
+ "handle": [
55
+ {
56
+ "handler": "rewrite",
57
+ "uri": "/b"
58
+ }
59
+ ],
60
+ "match": [
61
+ {
62
+ "path": [
63
+ "/path"
64
+ ]
65
+ }
66
+ ]
67
+ }
68
+ ]
69
+ },
70
+ {
71
+ "handler": "subroute",
72
+ "routes": [
73
+ {
74
+ "group": "group2",
75
+ "handle": [
76
+ {
77
+ "handler": "rewrite",
78
+ "uri": "/c"
79
+ }
80
+ ],
81
+ "match": [
82
+ {
83
+ "method": [
84
+ "GET"
85
+ ]
86
+ }
87
+ ]
88
+ }
89
+ ]
90
+ },
91
+ {
92
+ "handler": "subroute",
93
+ "routes": [
94
+ {
95
+ "group": "group3",
96
+ "handle": [
97
+ {
98
+ "handler": "rewrite",
99
+ "uri": "/d"
100
+ }
101
+ ]
102
+ }
103
+ ]
104
+ }
105
+ ]
106
+ }
107
+ ]
108
+ }
109
+ }
110
+ }
111
+ }
112
+}
\ No newline at end of file
caddytest/integration/caddyfile_adapt/root_directive_permutations.txt
new
+108
@@ -0,0 +1,108 @@
1
+:8080
2
+
3
+# With explicit wildcard matcher
4
+route {
5
+ root * /a
6
+}
7
+
8
+# With path matcher
9
+route {
10
+ root /path /b
11
+}
12
+
13
+# With named matcher
14
+route {
15
+ @named method GET
16
+ root @named /c
17
+}
18
+
19
+# With no matcher, assumed to be wildcard
20
+route {
21
+ root /d
22
+}
23
+----------
24
+{
25
+ "apps": {
26
+ "http": {
27
+ "servers": {
28
+ "srv0": {
29
+ "listen": [
30
+ ":8080"
31
+ ],
32
+ "routes": [
33
+ {
34
+ "handle": [
35
+ {
36
+ "handler": "subroute",
37
+ "routes": [
38
+ {
39
+ "handle": [
40
+ {
41
+ "handler": "vars",
42
+ "root": "/a"
43
+ }
44
+ ]
45
+ }
46
+ ]
47
+ },
48
+ {
49
+ "handler": "subroute",
50
+ "routes": [
51
+ {
52
+ "handle": [
53
+ {
54
+ "handler": "vars",
55
+ "root": "/b"
56
+ }
57
+ ],
58
+ "match": [
59
+ {
60
+ "path": [
61
+ "/path"
62
+ ]
63
+ }
64
+ ]
65
+ }
66
+ ]
67
+ },
68
+ {
69
+ "handler": "subroute",
70
+ "routes": [
71
+ {
72
+ "handle": [
73
+ {
74
+ "handler": "vars",
75
+ "root": "/c"
76
+ }
77
+ ],
78
+ "match": [
79
+ {
80
+ "method": [
81
+ "GET"
82
+ ]
83
+ }
84
+ ]
85
+ }
86
+ ]
87
+ },
88
+ {
89
+ "handler": "subroute",
90
+ "routes": [
91
+ {
92
+ "handle": [
93
+ {
94
+ "handler": "vars",
95
+ "root": "/d"
96
+ }
97
+ ]
98
+ }
99
+ ]
100
+ }
101
+ ]
102
+ }
103
+ ]
104
+ }
105
+ }
106
+ }
107
+ }
108
+}
\ No newline at end of file
modules/caddyhttp/rewrite/caddyfile.go
+40
-3
@@ -26,7 +26,7 @@ import (
26
)
27
28
func init() {
29
- httpcaddyfile.RegisterHandlerDirective("rewrite", parseCaddyfileRewrite)
29
+ httpcaddyfile.RegisterDirective("rewrite", parseCaddyfileRewrite)
30
httpcaddyfile.RegisterHandlerDirective("method", parseCaddyfileMethod)
31
httpcaddyfile.RegisterHandlerDirective("uri", parseCaddyfileURI)
32
httpcaddyfile.RegisterDirective("handle_path", parseCaddyfileHandlePath)
@@ -38,7 +38,44 @@ func init() {
38
//
39
// Only URI components which are given in <to> will be set in the resulting URI.
40
// See the docs for the rewrite handler for more information.
41
-func parseCaddyfileRewrite(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
41
+func parseCaddyfileRewrite(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error) {
42
+ // consume directive name
43
+ if !h.NextArg() {
44
+ return nil, h.ArgErr()
45
+ }
46
+
47
+ // count the tokens to determine what to do
48
+ argsCount := h.CountRemainingArgs()
49
+ if argsCount == 0 {
50
+ return nil, h.Errf("too few arguments; must have at least a rewrite URI")
51
+ }
52
+ if argsCount > 2 {
53
+ return nil, h.Errf("too many arguments; should only be a matcher and a URI")
54
+ }
55
+
56
+ // with only one arg, assume it's a rewrite URI with no matcher token
57
+ if argsCount == 1 {
58
+ if !h.NextArg() {
59
+ return nil, h.ArgErr()
60
+ }
61
+ return h.NewRoute(nil, Rewrite{URI: h.Val()}), nil
62
+ }
63
+
64
+ // parse the matcher token into a matcher set
65
+ userMatcherSet, err := h.ExtractMatcherSet()
66
+ if err != nil {
67
+ return nil, err
68
+ }
69
+
70
+ // consume directive name, again, because extracting matcher does a reset
71
+ if !h.NextArg() {
72
+ return nil, h.ArgErr()
73
+ }
74
+ // advance to the rewrite URI
75
+ if !h.NextArg() {
76
+ return nil, h.ArgErr()
77
+ }
78
+
79
var rewr Rewrite
80
for h.Next() {
81
if !h.NextArg() {
@@ -49,7 +86,7 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler,
86
return nil, h.ArgErr()
87
}
88
}
52
- return rewr, nil
89
+ return h.NewRoute(userMatcherSet, Rewrite{URI: h.Val()}), nil
90
}
91
92
// parseCaddyfileMethod sets up a basic method rewrite handler from Caddyfile tokens. Syntax: