Skip to content

Commit 5e2f1b5

Browse files
httpcaddyfile: Rewrite root and rewrite parsing to allow omitting matcher (#5844)
1 parent f3e849e commit 5e2f1b5

File tree

4 files changed

+296
-12
lines changed

4 files changed

+296
-12
lines changed

caddyconfig/httpcaddyfile/builtins.go

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func init() {
4141
RegisterDirective("bind", parseBind)
4242
RegisterDirective("tls", parseTLS)
4343
RegisterHandlerDirective("fs", parseFilesystem)
44-
RegisterHandlerDirective("root", parseRoot)
44+
RegisterDirective("root", parseRoot)
4545
RegisterHandlerDirective("vars", parseVars)
4646
RegisterHandlerDirective("redir", parseRedir)
4747
RegisterHandlerDirective("respond", parseRespond)
@@ -645,18 +645,45 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
645645
// parseRoot parses the root directive. Syntax:
646646
//
647647
// 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 {
651665
if !h.NextArg() {
652666
return nil, h.ArgErr()
653667
}
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()
658684
}
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
660687
}
661688

662689
// parseFilesystem parses the fs directive. Syntax:
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
}

modules/caddyhttp/rewrite/caddyfile.go

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
)
2727

2828
func init() {
29-
httpcaddyfile.RegisterHandlerDirective("rewrite", parseCaddyfileRewrite)
29+
httpcaddyfile.RegisterDirective("rewrite", parseCaddyfileRewrite)
3030
httpcaddyfile.RegisterHandlerDirective("method", parseCaddyfileMethod)
3131
httpcaddyfile.RegisterHandlerDirective("uri", parseCaddyfileURI)
3232
httpcaddyfile.RegisterDirective("handle_path", parseCaddyfileHandlePath)
@@ -38,7 +38,44 @@ func init() {
3838
//
3939
// Only URI components which are given in <to> will be set in the resulting URI.
4040
// 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+
4279
var rewr Rewrite
4380
for h.Next() {
4481
if !h.NextArg() {
@@ -49,7 +86,7 @@ func parseCaddyfileRewrite(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler,
4986
return nil, h.ArgErr()
5087
}
5188
}
52-
return rewr, nil
89+
return h.NewRoute(userMatcherSet, Rewrite{URI: h.Val()}), nil
5390
}
5491

5592
// parseCaddyfileMethod sets up a basic method rewrite handler from Caddyfile tokens. Syntax:

0 commit comments

Comments
 (0)