@marcel91200 / caddy Mirror · read-only / commits / a33e4b54
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 14, 05:15 UTC

caddyfile: Add support for `vars` and `vars_regexp` matchers (#3730)

* caddyfile: support vars and vars_regexp matchers in the caddyfile * caddyfile: matchers: Brian Kernighan said printf is good debugging tool but didn't say keep them around

Mohammed Al Sahaf committed Sep 26, 2020 at 02:50 UTC a33e4b542689cbe7ac711e3cfde1d2a30c0156ae
3 files changed +109
caddytest/integration/caddyfile_adapt/matcher_syntax.txt
+59
@@ -9,6 +9,15 @@
9
10 @matcher3 not method PUT
11 respond @matcher3 "not put"
12 +
13 + @matcher4 vars "{http.request.uri}" "/vars-matcher"
14 + respond @matcher4 "from vars matcher"
15 +
16 + @matcher5 vars_regexp static "{http.request.uri}" `\.([a-f0-9]{6})\.(css|js)$`
17 + respond @matcher5 "from vars_regexp matcher with name"
18 +
19 + @matcher6 vars_regexp "{http.request.uri}" `\.([a-f0-9]{6})\.(css|js)$`
20 + respond @matcher6 "from vars_regexp matcher without name"
21 }
22 ----------
23 {
@@ -68,6 +77,56 @@
77 "handler": "static_response"
78 }
79 ]
80 + },
81 + {
82 + "match": [
83 + {
84 + "vars": {
85 + "{http.request.uri}": "/vars-matcher"
86 + }
87 + }
88 + ],
89 + "handle": [
90 + {
91 + "body": "from vars matcher",
92 + "handler": "static_response"
93 + }
94 + ]
95 + },
96 + {
97 + "match": [
98 + {
99 + "vars_regexp": {
100 + "{http.request.uri}": {
101 + "name": "static",
102 + "pattern": "\\.([a-f0-9]{6})\\.(css|js)$"
103 + }
104 + }
105 + }
106 + ],
107 + "handle": [
108 + {
109 + "body": "from vars_regexp matcher with name",
110 + "handler": "static_response"
111 + }
112 + ]
113 + },
114 + {
115 + "match": [
116 + {
117 + "vars_regexp": {
118 + "{http.request.uri}": {
119 + "pattern": "\\.([a-f0-9]{6})\\.(css|js)$"
120 + }
121 + }
122 + }
123 + ],
124 + "handle": [
125 + {
126 + "body": "from vars_regexp matcher without name",
127 + "handler": "static_response"
128 + }
129 + ]
130 }
131 ]
132 }
modules/caddyhttp/matchers.go
+2
@@ -927,6 +927,8 @@ var (
927 _ caddyfile.Unmarshaler = (*MatchHeaderRE)(nil)
928 _ caddyfile.Unmarshaler = (*MatchProtocol)(nil)
929 _ caddyfile.Unmarshaler = (*MatchRemoteIP)(nil)
930 + _ caddyfile.Unmarshaler = (*VarsMatcher)(nil)
931 + _ caddyfile.Unmarshaler = (*MatchVarsRE)(nil)
932
933 _ json.Marshaler = (*MatchNot)(nil)
934 _ json.Unmarshaler = (*MatchNot)(nil)
modules/caddyhttp/vars.go
+48
@@ -20,6 +20,7 @@ import (
20 "net/http"
21
22 "github.com/caddyserver/caddy/v2"
23 + "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
24 )
25
26 func init() {
@@ -64,6 +65,24 @@ func (VarsMatcher) CaddyModule() caddy.ModuleInfo {
65 }
66 }
67
68 +// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
69 +func (m *VarsMatcher) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
70 + if *m == nil {
71 + *m = make(map[string]string)
72 + }
73 + for d.Next() {
74 + var field, val string
75 + if !d.Args(&field, &val) {
76 + return d.Errf("malformed vars matcher: expected both field and value")
77 + }
78 + (*m)[field] = val
79 + if d.NextBlock(0) {
80 + return d.Err("malformed vars matcher: blocks are not supported")
81 + }
82 + }
83 + return nil
84 +}
85 +
86 // Match matches a request based on variables in the context.
87 func (m VarsMatcher) Match(r *http.Request) bool {
88 vars := r.Context().Value(VarsCtxKey).(map[string]interface{})
@@ -106,6 +125,35 @@ func (MatchVarsRE) CaddyModule() caddy.ModuleInfo {
125 }
126 }
127
128 +// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
129 +func (m *MatchVarsRE) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
130 + if *m == nil {
131 + *m = make(map[string]*MatchRegexp)
132 + }
133 + for d.Next() {
134 + var first, second, third string
135 + if !d.Args(&first, &second) {
136 + return d.ArgErr()
137 + }
138 +
139 + var name, field, val string
140 + if d.Args(&third) {
141 + name = first
142 + field = second
143 + val = third
144 + } else {
145 + field = first
146 + val = second
147 + }
148 +
149 + (*m)[field] = &MatchRegexp{Pattern: val, Name: name}
150 + if d.NextBlock(0) {
151 + return d.Err("malformed vars_regexp matcher: blocks are not supported")
152 + }
153 + }
154 + return nil
155 +}
156 +
157 // Provision compiles m's regular expressions.
158 func (m MatchVarsRE) Provision(ctx caddy.Context) error {
159 for _, rm := range m {