httpcaddyfile: Matchers can now be embedded into a nested scope

This is useful in 'handle' and 'route' directives, for instance, if you
want to keep your matcher definitions by the directives that use them.
This commit is contained in:
Matthew Holt 2020-02-25 21:56:43 -07:00
parent 78760c0ddc
commit f6b9cb7122
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5

View file

@ -17,6 +17,7 @@ package httpcaddyfile
import ( import (
"encoding/json" "encoding/json"
"sort" "sort"
"strings"
"github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2"
"github.com/caddyserver/caddy/v2/caddyconfig" "github.com/caddyserver/caddy/v2/caddyconfig"
@ -298,17 +299,43 @@ func sortRoutes(routes []ConfigValue) {
// and returned. // and returned.
func parseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) { func parseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) {
var allResults []ConfigValue var allResults []ConfigValue
for h.Next() {
for nesting := h.Nesting(); h.NextBlock(nesting); {
dir := h.Val()
for h.Next() {
// slice the linear list of tokens into top-level segments
var segments []caddyfile.Segment
for nesting := h.Nesting(); h.NextBlock(nesting); {
segments = append(segments, h.NextSegment())
}
// copy existing matcher definitions so we can augment
// new ones that are defined only in this scope
matcherDefs := make(map[string]caddy.ModuleMap, len(h.matcherDefs))
for key, val := range h.matcherDefs {
matcherDefs[key] = val
}
// find and extract any embedded matcher definitions in this scope
for i, seg := range segments {
if strings.HasPrefix(seg.Directive(), matcherPrefix) {
err := parseMatcherDefinitions(caddyfile.NewDispenser(seg), matcherDefs)
if err != nil {
return nil, err
}
segments = append(segments[:i], segments[i+1:]...)
}
}
// with matchers ready to go, evaluate each directive's segment
for _, seg := range segments {
dir := seg.Directive()
dirFunc, ok := registeredDirectives[dir] dirFunc, ok := registeredDirectives[dir]
if !ok { if !ok {
return nil, h.Errf("unrecognized directive: %s", dir) return nil, h.Errf("unrecognized directive: %s", dir)
} }
subHelper := h subHelper := h
subHelper.Dispenser = h.NewFromNextSegment() subHelper.Dispenser = caddyfile.NewDispenser(seg)
subHelper.matcherDefs = matcherDefs
results, err := dirFunc(subHelper) results, err := dirFunc(subHelper)
if err != nil { if err != nil {
@ -319,9 +346,9 @@ func parseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) {
allResults = append(allResults, result) allResults = append(allResults, result)
} }
} }
return buildSubroute(allResults, h.groupCounter) // TODO: should we move this outside the loop?
} }
return nil, nil
return buildSubroute(allResults, h.groupCounter)
} }
// serverBlock pairs a Caddyfile server block // serverBlock pairs a Caddyfile server block