diff options
Diffstat (limited to 'modules/caddyhttp/vars.go')
-rw-r--r-- | modules/caddyhttp/vars.go | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/modules/caddyhttp/vars.go b/modules/caddyhttp/vars.go index 1208d9c..9561d46 100644 --- a/modules/caddyhttp/vars.go +++ b/modules/caddyhttp/vars.go @@ -25,6 +25,7 @@ import ( func init() { caddy.RegisterModule(VarsMiddleware{}) caddy.RegisterModule(VarsMatcher{}) + caddy.RegisterModule(MatchVarsRE{}) } // VarsMiddleware is an HTTP middleware which sets variables @@ -88,6 +89,74 @@ func (m VarsMatcher) Match(r *http.Request) bool { return true } +// MatchVarsRE matches the value of the context variables by a given regular expression. +// +// Upon a match, it adds placeholders to the request: `{http.regexp.name.capture_group}` +// where `name` is the regular expression's name, and `capture_group` is either +// the named or positional capture group from the expression itself. If no name +// is given, then the placeholder omits the name: `{http.regexp.capture_group}` +// (potentially leading to collisions). +type MatchVarsRE map[string]*MatchRegexp + +// CaddyModule returns the Caddy module information. +func (MatchVarsRE) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + ID: "http.matchers.vars_regexp", + New: func() caddy.Module { return new(MatchVarsRE) }, + } +} + +// Provision compiles m's regular expressions. +func (m MatchVarsRE) Provision(ctx caddy.Context) error { + for _, rm := range m { + err := rm.Provision(ctx) + if err != nil { + return err + } + } + return nil +} + +// Match returns true if r matches m. +func (m MatchVarsRE) Match(r *http.Request) bool { + vars := r.Context().Value(VarsCtxKey).(map[string]interface{}) + repl := r.Context().Value(caddy.ReplacerCtxKey).(*caddy.Replacer) + for k, rm := range m { + var varStr string + switch vv := vars[k].(type) { + case string: + varStr = vv + case fmt.Stringer: + varStr = vv.String() + case error: + varStr = vv.Error() + default: + varStr = fmt.Sprintf("%v", vv) + } + valExpanded := repl.ReplaceAll(varStr, "") + if match := rm.Match(valExpanded, repl); match { + return match + } + + replacedVal := repl.ReplaceAll(k, "") + if match := rm.Match(replacedVal, repl); match { + return match + } + } + return false +} + +// Validate validates m's regular expressions. +func (m MatchVarsRE) Validate() error { + for _, rm := range m { + err := rm.Validate() + if err != nil { + return err + } + } + return nil +} + // GetVar gets a value out of the context's variable table by key. // If the key does not exist, the return value will be nil. func GetVar(ctx context.Context, key string) interface{} { |