mirror of
https://github.com/caddyserver/caddy.git
synced 2025-10-19 15:53:17 +00:00
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.
This commit is contained in:
parent
bc00d840e8
commit
284fb3a98c
4 changed files with 133 additions and 61 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue