func parseSegmentAsConfig(h Helper) ([]ConfigValue, error) {
	var allResults []ConfigValue
	for h.Next() {
		if h.NextArg() {
			return nil, h.ArgErr()
		}
		var segments []caddyfile.Segment
		for nesting := h.Nesting(); h.NextBlock(nesting); {
			segments = append(segments, h.NextSegment())
		}
		matcherDefs := make(map[string]caddy.ModuleMap, len(h.matcherDefs))
		for key, val := range h.matcherDefs {
			matcherDefs[key] = val
		}
		for i := 0; i < len(segments); i++ {
			seg := segments[i]
			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:]...)
				i--
			}
		}
		for _, seg := range segments {
			dir := seg.Directive()
			dirFunc, ok := registeredDirectives[dir]
			if !ok {
				return nil, h.Errf("unrecognized directive: %s - are you sure your Caddyfile structure (nesting and braces) is correct?", dir)
			}
			subHelper := h
			subHelper.Dispenser = caddyfile.NewDispenser(seg)
			subHelper.matcherDefs = matcherDefs
			results, err := dirFunc(subHelper)
			if err != nil {
				return nil, h.Errf("parsing caddyfile tokens for '%s': %v", dir, err)
			}
			for _, result := range results {
				result.directive = dir
				allResults = append(allResults, result)
			}
		}
	}
	return allResults, nil
}
parseSegmentAsConfig parses the segment such that its subdirectives
are themselves treated as directives, including named matcher definitions,
and the raw Config structs are returned.
package httpcaddyfile
import (
	"encoding/json"
	"net"
	"sort"
	"strconv"
	"strings"
	"github.com/caddyserver/caddy/v2"
	"github.com/caddyserver/caddy/v2/caddyconfig"
	"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
	"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
var directiveOrder = []string{
	"map",
	"root",
	"header",
	"request_body",
	"redir",
	"rewrite",
	"uri",
	"try_files",
	"basicauth",
	"request_header",
	"encode",
	"push",
	"templates",
	"handle",
	"handle_path",
	"route",
	"abort",
	"error",
	"respond",
	"metrics",
	"reverse_proxy",
	"php_fastcgi",
	"file_server",
	"acme_server",
}
func directiveIsOrdered(dir string) bool {
	for _, d := range directiveOrder {
		if d == dir {
			return true
		}
	}
	return false
}
func RegisterDirective(dir string, setupFunc UnmarshalFunc) {
	if _, ok := registeredDirectives[dir]; ok {
		panic("directive " + dir + " already registered")
	}
	registeredDirectives[dir] = setupFunc
}
func RegisterHandlerDirective(dir string, setupFunc UnmarshalHandlerFunc) {
	RegisterDirective(dir, func(h Helper) ([]ConfigValue, error) {
		if !h.Next() {
			return nil, h.ArgErr()
		}
		matcherSet, err := h.ExtractMatcherSet()
		if err != nil {
			return nil, err
		}
		val, err := setupFunc(h)
		if err != nil {
			return nil, err
		}
		return h.NewRoute(matcherSet, val), nil
	})
}
func RegisterGlobalOption(opt string, setupFunc UnmarshalGlobalFunc) {
	if _, ok := registeredGlobalOptions[opt]; ok {
		panic("global option " + opt + " already registered")
	}
	registeredGlobalOptions[opt] = setupFunc
}
type Helper struct {
	*caddyfile.Dispenser
	State        map[string]interface{}
	options      map[string]interface{}
	warnings     *[]caddyconfig.Warning
	matcherDefs  map[string]caddy.ModuleMap
	parentBlock  caddyfile.ServerBlock
	groupCounter counter
}
func (h Helper) Option(name string) interface{} {
	return h.options[name]
}
func (h Helper) Caddyfiles() []string {
	files := make(map[string]struct{})
	for _, segment := range h.parentBlock.Segments {
		for _, token := range segment {
			files[token.File] = struct{}{}
		}
	}
	filesSlice := make([]string, 0, len(files))
	for file := range files {
		filesSlice = append(filesSlice, file)
	}
	return filesSlice
}
func (h Helper) JSON(val interface{}) json.RawMessage {
	return caddyconfig.JSON(val, h.warnings)
}
func (h Helper) MatcherToken() (caddy.ModuleMap, bool, error) {
	if !h.NextArg() {
		return nil, false, nil
	}
	return matcherSetFromMatcherToken(h.Dispenser.Token(), h.matcherDefs, h.warnings)
}
func (h Helper) ExtractMatcherSet() (caddy.ModuleMap, error) {
	matcherSet, hasMatcher, err := h.MatcherToken()
	if err != nil {
		return nil, err
	}
	if hasMatcher {
		h.Dispenser.Delete()
	}
	h.Dispenser.Reset()  
	return matcherSet, nil
}
func (h Helper) NewRoute(matcherSet caddy.ModuleMap,
	handler caddyhttp.MiddlewareHandler) []ConfigValue {
	mod, err := caddy.GetModule(caddy.GetModuleID(handler))
	if err != nil {
		*h.warnings = append(*h.warnings, caddyconfig.Warning{
			File:    h.File(),
			Line:    h.Line(),
			Message: err.Error(),
		})
		return nil
	}
	var matcherSetsRaw []caddy.ModuleMap
	if matcherSet != nil {
		matcherSetsRaw = append(matcherSetsRaw, matcherSet)
	}
	return []ConfigValue{
		{
			Class: "route",
			Value: caddyhttp.Route{
				MatcherSetsRaw: matcherSetsRaw,
				HandlersRaw:    []json.RawMessage{caddyconfig.JSONModuleObject(handler, "handler", mod.ID.Name(), h.warnings)},
			},
		},
	}
}
func (h Helper) GroupRoutes(vals []ConfigValue) {
	var count int
	for _, v := range vals {
		if _, ok := v.Value.(caddyhttp.Route); ok {
			count++
			if count > 1 {
				break
			}
		}
	}
	if count < 2 {
		return
	}
	groupName := h.groupCounter.nextGroup()
	for i := range vals {
		if route, ok := vals[i].Value.(caddyhttp.Route); ok {
			route.Group = groupName
			vals[i].Value = route
		}
	}
}
func (h Helper) NewBindAddresses(addrs []string) []ConfigValue {
	return []ConfigValue{{Class: "bind", Value: addrs}}
}
func (h Helper) WithDispenser(d *caddyfile.Dispenser) Helper {
	h.Dispenser = d
	return h
}
func ParseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) {
	allResults, err := parseSegmentAsConfig(h)
	if err != nil {
		return nil, err
	}
	return buildSubroute(allResults, h.groupCounter)
}