@@ -59,8 +59,15 @@ func (t VarsMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next H
5959}
6060
6161// VarsMatcher is an HTTP request matcher which can match
62- // requests based on variables in the context.
63- type VarsMatcher map [string ]string
62+ // requests based on variables in the context. The key is
63+ // the name of the variable, and the values are possible
64+ // values the variable can be in order to match (OR'ed).
65+ //
66+ // As a special case, this matcher can also match on
67+ // placeholders generally. If the key is not an HTTP chain
68+ // variable, it will be checked to see if it is a
69+ // placeholder name, and if so, will compare its value.
70+ type VarsMatcher map [string ][]string
6471
6572// CaddyModule returns the Caddy module information.
6673func (VarsMatcher ) CaddyModule () caddy.ModuleInfo {
@@ -73,44 +80,65 @@ func (VarsMatcher) CaddyModule() caddy.ModuleInfo {
7380// UnmarshalCaddyfile implements caddyfile.Unmarshaler.
7481func (m * VarsMatcher ) UnmarshalCaddyfile (d * caddyfile.Dispenser ) error {
7582 if * m == nil {
76- * m = make (map [string ]string )
83+ * m = make (map [string ][] string )
7784 }
7885 for d .Next () {
79- var field , val string
80- if ! d .Args (& field , & val ) {
81- return d .Errf ("malformed vars matcher: expected both field and value" )
86+ var field string
87+ if ! d .Args (& field ) {
88+ return d .Errf ("malformed vars matcher: expected field name" )
89+ }
90+ vals := d .RemainingArgs ()
91+ if len (vals ) == 0 {
92+ return d .Errf ("malformed vars matcher: expected at least one value to match against" )
8293 }
83- (* m )[field ] = val
94+ (* m )[field ] = vals
8495 if d .NextBlock (0 ) {
8596 return d .Err ("malformed vars matcher: blocks are not supported" )
8697 }
8798 }
8899 return nil
89100}
90101
91- // Match matches a request based on variables in the context.
102+ // Match matches a request based on variables in the context,
103+ // or placeholders if the key is not a variable.
92104func (m VarsMatcher ) Match (r * http.Request ) bool {
105+ if len (m ) == 0 {
106+ return true
107+ }
108+
93109 vars := r .Context ().Value (VarsCtxKey ).(map [string ]interface {})
94110 repl := r .Context ().Value (caddy .ReplacerCtxKey ).(* caddy.Replacer )
95- for k , v := range m {
96- keyExpanded := repl .ReplaceAll (k , "" )
97- valExpanded := repl .ReplaceAll (v , "" )
98- var varStr string
99- switch vv := vars [keyExpanded ].(type ) {
100- case string :
101- varStr = vv
102- case fmt.Stringer :
103- varStr = vv .String ()
104- case error :
105- varStr = vv .Error ()
106- default :
107- varStr = fmt .Sprintf ("%v" , vv )
111+
112+ for key , vals := range m {
113+ // look up the comparison value we will check against with this key
114+ matcherVarNameExpanded := repl .ReplaceAll (key , "" )
115+ varValue , ok := vars [matcherVarNameExpanded ]
116+ if ! ok {
117+ // as a special case, if it's not an HTTP variable,
118+ // see if it's a placeholder name
119+ varValue , _ = repl .Get (matcherVarNameExpanded )
108120 }
109- if varStr != valExpanded {
110- return false
121+
122+ // see if any of the values given in the matcher match the actual value
123+ for _ , v := range vals {
124+ matcherValExpanded := repl .ReplaceAll (v , "" )
125+ var varStr string
126+ switch vv := varValue .(type ) {
127+ case string :
128+ varStr = vv
129+ case fmt.Stringer :
130+ varStr = vv .String ()
131+ case error :
132+ varStr = vv .Error ()
133+ default :
134+ varStr = fmt .Sprintf ("%v" , vv )
135+ }
136+ if varStr == matcherValExpanded {
137+ return true
138+ }
111139 }
112140 }
113- return true
141+ return false
114142}
115143
116144// MatchVarsRE matches the value of the context variables by a given regular expression.
0 commit comments