summaryrefslogtreecommitdiff
path: root/caddyconfig/httpcaddyfile/directives.go
diff options
context:
space:
mode:
Diffstat (limited to 'caddyconfig/httpcaddyfile/directives.go')
-rw-r--r--caddyconfig/httpcaddyfile/directives.go62
1 files changed, 42 insertions, 20 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go
index f82e2a8..e7a9686 100644
--- a/caddyconfig/httpcaddyfile/directives.go
+++ b/caddyconfig/httpcaddyfile/directives.go
@@ -114,6 +114,8 @@ func RegisterHandlerDirective(dir string, setupFunc UnmarshalHandlerFunc) {
// Caddyfile tokens.
type Helper struct {
*caddyfile.Dispenser
+ // State stores intermediate variables during caddyfile adaptation.
+ State map[string]interface{}
options map[string]interface{}
warnings *[]caddyconfig.Warning
matcherDefs map[string]caddy.ModuleMap
@@ -161,6 +163,23 @@ func (h Helper) MatcherToken() (caddy.ModuleMap, bool, error) {
return matcherSetFromMatcherToken(h.Dispenser.Token(), h.matcherDefs, h.warnings)
}
+// ExtractMatcherSet is like MatcherToken, except this is a higher-level
+// method that returns the matcher set described by the matcher token,
+// or nil if there is none, and deletes the matcher token from the
+// dispenser and resets it as if this look-ahead never happened. Useful
+// when wrapping a route (one or more handlers) in a user-defined matcher.
+func (h Helper) ExtractMatcherSet() (caddy.ModuleMap, error) {
+ matcherSet, hasMatcher, err := h.MatcherToken()
+ if err != nil {
+ return nil, err
+ }
+ if hasMatcher {
+ h.Dispenser.Delete() // strip matcher token
+ }
+ h.Dispenser.Reset() // pretend this lookahead never happened
+ return matcherSet, nil
+}
+
// NewRoute returns config values relevant to creating a new HTTP route.
func (h Helper) NewRoute(matcherSet caddy.ModuleMap,
handler caddyhttp.MiddlewareHandler) []ConfigValue {
@@ -266,28 +285,31 @@ func sortRoutes(routes []ConfigValue) {
return false
}
- if len(iRoute.MatcherSetsRaw) == 1 && len(jRoute.MatcherSetsRaw) == 1 {
- // use already-decoded matcher, or decode if it's the first time seeing it
- iPM, jPM := decodedMatchers[i], decodedMatchers[j]
- if iPM == nil {
- var pathMatcher caddyhttp.MatchPath
- _ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &pathMatcher)
- decodedMatchers[i] = pathMatcher
- iPM = pathMatcher
- }
- if jPM == nil {
- var pathMatcher caddyhttp.MatchPath
- _ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &pathMatcher)
- decodedMatchers[j] = pathMatcher
- jPM = pathMatcher
- }
+ // use already-decoded matcher, or decode if it's the first time seeing it
+ iPM, jPM := decodedMatchers[i], decodedMatchers[j]
+ if iPM == nil && len(iRoute.MatcherSetsRaw) == 1 {
+ var pathMatcher caddyhttp.MatchPath
+ _ = json.Unmarshal(iRoute.MatcherSetsRaw[0]["path"], &pathMatcher)
+ decodedMatchers[i] = pathMatcher
+ iPM = pathMatcher
+ }
+ if jPM == nil && len(jRoute.MatcherSetsRaw) == 1 {
+ var pathMatcher caddyhttp.MatchPath
+ _ = json.Unmarshal(jRoute.MatcherSetsRaw[0]["path"], &pathMatcher)
+ decodedMatchers[j] = pathMatcher
+ jPM = pathMatcher
+ }
- // if there is only one path in the matcher, sort by
- // longer path (more specific) first
- if len(iPM) == 1 && len(jPM) == 1 {
- return len(iPM[0]) > len(jPM[0])
- }
+ // sort by longer path (more specific) first; missing
+ // path matchers are treated as zero-length paths
+ var iPathLen, jPathLen int
+ if iPM != nil {
+ iPathLen = len(iPM[0])
+ }
+ if jPM != nil {
+ jPathLen = len(jPM[0])
}
+ return iPathLen > jPathLen
}
return dirPositions[iDir] < dirPositions[jDir]