@marcel91200 / caddy Mirror · read-only / commits / 5e2f1b5c
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, 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: