diff options
Diffstat (limited to 'modules/caddyhttp')
-rw-r--r-- | modules/caddyhttp/routes.go | 110 |
1 files changed, 68 insertions, 42 deletions
diff --git a/modules/caddyhttp/routes.go b/modules/caddyhttp/routes.go index 108bb15..9dca107 100644 --- a/modules/caddyhttp/routes.go +++ b/modules/caddyhttp/routes.go @@ -26,13 +26,13 @@ import ( // middlewares, and a responder for handling HTTP // requests. type Route struct { - Group string `json:"group,omitempty"` - MatcherSetsRaw []map[string]json.RawMessage `json:"match,omitempty"` - HandlersRaw []json.RawMessage `json:"handle,omitempty"` - Terminal bool `json:"terminal,omitempty"` + Group string `json:"group,omitempty"` + MatcherSetsRaw RawMatcherSets `json:"match,omitempty"` + HandlersRaw []json.RawMessage `json:"handle,omitempty"` + Terminal bool `json:"terminal,omitempty"` // decoded values - MatcherSets []MatcherSet `json:"-"` + MatcherSets MatcherSets `json:"-"` Handlers []MiddlewareHandler `json:"-"` } @@ -46,32 +46,6 @@ func (r Route) Empty() bool { r.Group == "" } -func (r Route) anyMatcherSetMatches(req *http.Request) bool { - for _, ms := range r.MatcherSets { - if ms.Match(req) { - return true - } - } - // if no matchers, always match - return len(r.MatcherSets) == 0 -} - -// MatcherSet is a set of matchers which -// must all match in order for the request -// to be matched successfully. -type MatcherSet []RequestMatcher - -// Match returns true if the request matches all -// matchers in mset. -func (mset MatcherSet) Match(r *http.Request) bool { - for _, m := range mset { - if !m.Match(r) { - return false - } - } - return true -} - // RouteList is a list of server routes that can // create a middleware chain. type RouteList []Route @@ -80,17 +54,11 @@ type RouteList []Route func (routes RouteList) Provision(ctx caddy.Context) error { for i, route := range routes { // matchers - for _, matcherSet := range route.MatcherSetsRaw { - var matchers MatcherSet - for modName, rawMsg := range matcherSet { - val, err := ctx.LoadModule("http.matchers."+modName, rawMsg) - if err != nil { - return fmt.Errorf("loading matcher module '%s': %v", modName, err) - } - matchers = append(matchers, val.(RequestMatcher)) - } - routes[i].MatcherSets = append(routes[i].MatcherSets, matchers) + matcherSets, err := route.MatcherSetsRaw.Setup(ctx) + if err != nil { + return err } + routes[i].MatcherSets = matcherSets routes[i].MatcherSetsRaw = nil // allow GC to deallocate // handlers @@ -118,7 +86,7 @@ func (routes RouteList) BuildCompositeRoute(req *http.Request) Handler { for _, route := range routes { // route must match at least one of the matcher sets - if !route.anyMatcherSetMatches(req) { + if !route.MatcherSets.AnyMatch(req) { continue } @@ -181,3 +149,61 @@ func wrapMiddleware(mh MiddlewareHandler) Middleware { } } } + +// MatcherSet is a set of matchers which +// must all match in order for the request +// to be matched successfully. +type MatcherSet []RequestMatcher + +// Match returns true if the request matches all +// matchers in mset. +func (mset MatcherSet) Match(r *http.Request) bool { + for _, m := range mset { + if !m.Match(r) { + return false + } + } + return true +} + +// RawMatcherSets is a group of matcher sets +// in their raw, JSON form. +type RawMatcherSets []map[string]json.RawMessage + +// Setup sets up all matcher sets by loading each matcher module +// and returning the group of provisioned matcher sets. +func (rm RawMatcherSets) Setup(ctx caddy.Context) (MatcherSets, error) { + if rm == nil { + return nil, nil + } + var ms MatcherSets + for _, matcherSet := range rm { + var matchers MatcherSet + for modName, rawMsg := range matcherSet { + val, err := ctx.LoadModule("http.matchers."+modName, rawMsg) + if err != nil { + return nil, fmt.Errorf("loading matcher module '%s': %v", modName, err) + } + matchers = append(matchers, val.(RequestMatcher)) + } + ms = append(ms, matchers) + } + return ms, nil +} + +// MatcherSets is a group of matcher sets capable +// of checking whether a request matches any of +// the sets. +type MatcherSets []MatcherSet + +// AnyMatch returns true if req matches any of the +// matcher sets in mss or if there are no matchers, +// in which case the request always matches. +func (mss MatcherSets) AnyMatch(req *http.Request) bool { + for _, ms := range mss { + if ms.Match(req) { + return true + } + } + return len(mss) == 0 +} |