summaryrefslogtreecommitdiff
path: root/modules/caddyhttp/routes.go
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2019-05-22 13:13:39 -0600
committerMatthew Holt <mholt@users.noreply.github.com>2019-05-22 13:13:39 -0600
commit284fb3a98cae2e6e6ca79327988230a3a916996a (patch)
treeee52b5d7f144cf6510d1689e1ce06887ec213685 /modules/caddyhttp/routes.go
parentbc00d840e845d42145954839b88f1e836cd51bfd (diff)
Allow multiple matcher sets in routes (OR'ed together)
Also export MatchRegexp in case other matcher modules find it useful. Add comments to the exported matchers.
Diffstat (limited to 'modules/caddyhttp/routes.go')
-rw-r--r--modules/caddyhttp/routes.go64
1 files changed, 45 insertions, 19 deletions
diff --git a/modules/caddyhttp/routes.go b/modules/caddyhttp/routes.go
index 07e0566..59f287e 100644
--- a/modules/caddyhttp/routes.go
+++ b/modules/caddyhttp/routes.go
@@ -12,17 +12,42 @@ import (
// middlewares, and a responder for handling HTTP
// requests.
type ServerRoute struct {
- Group string `json:"group,omitempty"`
- Matchers map[string]json.RawMessage `json:"match,omitempty"`
- Apply []json.RawMessage `json:"apply,omitempty"`
- Respond json.RawMessage `json:"respond,omitempty"`
+ Group string `json:"group,omitempty"`
+ MatcherSets []map[string]json.RawMessage `json:"match,omitempty"`
+ Apply []json.RawMessage `json:"apply,omitempty"`
+ Respond json.RawMessage `json:"respond,omitempty"`
Terminal bool `json:"terminal,omitempty"`
// decoded values
- matchers []RequestMatcher
- middleware []MiddlewareHandler
- responder Handler
+ matcherSets []MatcherSet
+ middleware []MiddlewareHandler
+ responder Handler
+}
+
+func (sr ServerRoute) anyMatcherSetMatches(r *http.Request) bool {
+ for _, ms := range sr.matcherSets {
+ if ms.Match(r) {
+ return true
+ }
+ }
+ return false
+}
+
+// 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
@@ -33,14 +58,18 @@ type RouteList []ServerRoute
func (routes RouteList) Provision(ctx caddy2.Context) error {
for i, route := range routes {
// matchers
- for modName, rawMsg := range route.Matchers {
- val, err := ctx.LoadModule("http.matchers."+modName, rawMsg)
- if err != nil {
- return fmt.Errorf("loading matcher module '%s': %v", modName, err)
+ for _, matcherSet := range route.MatcherSets {
+ 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].matchers = append(routes[i].matchers, val.(RequestMatcher))
+ routes[i].matcherSets = append(routes[i].matcherSets, matchers)
}
- routes[i].Matchers = nil // allow GC to deallocate - TODO: Does this help?
+ routes[i].MatcherSets = nil // allow GC to deallocate - TODO: Does this help?
// middleware
for j, rawMsg := range route.Apply {
@@ -78,13 +107,10 @@ func (routes RouteList) BuildCompositeRoute(rw http.ResponseWriter, req *http.Re
var responder Handler
groups := make(map[string]struct{})
-routeLoop:
for _, route := range routes {
- // see if route matches
- for _, m := range route.matchers {
- if !m.Match(req) {
- continue routeLoop
- }
+ // route must match at least one of the matcher sets
+ if !route.anyMatcherSetMatches(req) {
+ continue
}
// if route is part of a group, ensure only