summaryrefslogtreecommitdiff
path: root/caddyconfig
diff options
context:
space:
mode:
authorMatthew Holt <mholt@users.noreply.github.com>2020-02-16 22:24:20 -0700
committerMatthew Holt <mholt@users.noreply.github.com>2020-02-16 22:24:20 -0700
commit23cc26d585bfbbe06ae8d2f46fa64956e368baac (patch)
treedb3212f2e97f5796383990bea68319b669f8badf /caddyconfig
parentbc2e406572e9af290469b2d4d58974ac99c0b492 (diff)
httpcaddyfile: 'handle_errors' directive
Not sure I love the name of the directive; might change it later.
Diffstat (limited to 'caddyconfig')
-rw-r--r--caddyconfig/httpcaddyfile/builtins.go44
-rw-r--r--caddyconfig/httpcaddyfile/directives.go33
-rw-r--r--caddyconfig/httpcaddyfile/httptype.go49
3 files changed, 85 insertions, 41 deletions
diff --git a/caddyconfig/httpcaddyfile/builtins.go b/caddyconfig/httpcaddyfile/builtins.go
index b758c39..7ad4a20 100644
--- a/caddyconfig/httpcaddyfile/builtins.go
+++ b/caddyconfig/httpcaddyfile/builtins.go
@@ -35,7 +35,8 @@ func init() {
RegisterHandlerDirective("redir", parseRedir)
RegisterHandlerDirective("respond", parseRespond)
RegisterHandlerDirective("route", parseRoute)
- RegisterHandlerDirective("handle", parseHandle)
+ RegisterHandlerDirective("handle", parseSegmentAsSubroute)
+ RegisterDirective("handle_errors", parseHandleErrors)
}
// parseBind parses the bind directive. Syntax:
@@ -235,7 +236,7 @@ func parseTLS(h Helper) ([]ConfigValue, error) {
return nil, h.Errf("getting DNS provider module named '%s': %v", provName, err)
}
mgr.Challenges.DNSRaw = caddyconfig.JSONModuleObject(dnsProvModule.New(), "provider", provName, h.warnings)
-
+
case "ca_root":
arg := h.RemainingArgs()
if len(arg) != 1 {
@@ -387,36 +388,21 @@ func parseRoute(h Helper) (caddyhttp.MiddlewareHandler, error) {
return sr, nil
}
-// parseHandle parses the route directive.
func parseHandle(h Helper) (caddyhttp.MiddlewareHandler, error) {
- var allResults []ConfigValue
-
- for h.Next() {
- for nesting := h.Nesting(); h.NextBlock(nesting); {
- dir := h.Val()
-
- dirFunc, ok := registeredDirectives[dir]
- if !ok {
- return nil, h.Errf("unrecognized directive: %s", dir)
- }
-
- subHelper := h
- subHelper.Dispenser = h.NewFromNextSegment()
-
- 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 parseSegmentAsSubroute(h)
+}
- return buildSubroute(allResults, h.groupCounter)
+func parseHandleErrors(h Helper) ([]ConfigValue, error) {
+ subroute, err := parseSegmentAsSubroute(h)
+ if err != nil {
+ return nil, err
}
-
- return nil, nil
+ return []ConfigValue{
+ {
+ Class: "error_route",
+ Value: subroute,
+ },
+ }, nil
}
var tagCounter = 0
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go
index 035dcbe..3c03d30 100644
--- a/caddyconfig/httpcaddyfile/directives.go
+++ b/caddyconfig/httpcaddyfile/directives.go
@@ -37,6 +37,7 @@ var directiveOrder = []string{
"uri_replace",
"try_files",
+ // middleware handlers that typically wrap responses
"basicauth",
"header",
"request_header",
@@ -46,6 +47,7 @@ var directiveOrder = []string{
"handle",
"route",
+ // handlers that typically respond to requests
"respond",
"reverse_proxy",
"php_fastcgi",
@@ -291,6 +293,37 @@ func sortRoutes(routes []ConfigValue) {
})
}
+// parseSegmentAsSubroute parses the segment such that its subdirectives
+// are themselves treated as directives, from which a subroute is built
+// and returned.
+func parseSegmentAsSubroute(h Helper) (caddyhttp.MiddlewareHandler, error) {
+ var allResults []ConfigValue
+ for h.Next() {
+ for nesting := h.Nesting(); h.NextBlock(nesting); {
+ dir := h.Val()
+
+ dirFunc, ok := registeredDirectives[dir]
+ if !ok {
+ return nil, h.Errf("unrecognized directive: %s", dir)
+ }
+
+ subHelper := h
+ subHelper.Dispenser = h.NewFromNextSegment()
+
+ 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 buildSubroute(allResults, h.groupCounter) // TODO: should we move this outside the loop?
+ }
+ return nil, nil
+}
+
// serverBlock pairs a Caddyfile server block
// with a "pile" of config values, keyed by class
// name.
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go
index f93b8c5..7c13794 100644
--- a/caddyconfig/httpcaddyfile/httptype.go
+++ b/caddyconfig/httpcaddyfile/httptype.go
@@ -474,18 +474,18 @@ func (st *ServerType) serversFromPairings(
return nil, err
}
- if len(matcherSetsEnc) == 0 && len(p.serverBlocks) == 1 {
- // no need to wrap the handlers in a subroute if this is
- // the only server block and there is no matcher for it
- srv.Routes = append(srv.Routes, siteSubroute.Routes...)
- } else {
- srv.Routes = append(srv.Routes, caddyhttp.Route{
- MatcherSetsRaw: matcherSetsEnc,
- HandlersRaw: []json.RawMessage{
- caddyconfig.JSONModuleObject(siteSubroute, "handler", "subroute", warnings),
- },
- Terminal: true, // only first matching site block should be evaluated
- })
+ // add the site block's route(s) to the server
+ srv.Routes = appendSubrouteToRouteList(srv.Routes, siteSubroute, matcherSetsEnc, p, warnings)
+
+ // if error routes are defined, add those too
+ if errorSubrouteVals, ok := sblock.pile["error_route"]; ok {
+ if srv.Errors == nil {
+ srv.Errors = new(caddyhttp.HTTPErrorConfig)
+ }
+ for _, val := range errorSubrouteVals {
+ sr := val.Value.(*caddyhttp.Subroute)
+ srv.Errors.Routes = appendSubrouteToRouteList(srv.Errors.Routes, sr, matcherSetsEnc, p, warnings)
+ }
}
}
@@ -497,6 +497,31 @@ func (st *ServerType) serversFromPairings(
return servers, nil
}
+// appendSubrouteToRouteList appends the routes in subroute
+// to the routeList, optionally qualified by matchers.
+func appendSubrouteToRouteList(routeList caddyhttp.RouteList,
+ subroute *caddyhttp.Subroute,
+ matcherSetsEnc []caddy.ModuleMap,
+ p sbAddrAssociation,
+ warnings *[]caddyconfig.Warning) caddyhttp.RouteList {
+ if len(matcherSetsEnc) == 0 && len(p.serverBlocks) == 1 {
+ // no need to wrap the handlers in a subroute if this is
+ // the only server block and there is no matcher for it
+ routeList = append(routeList, subroute.Routes...)
+ } else {
+ routeList = append(routeList, caddyhttp.Route{
+ MatcherSetsRaw: matcherSetsEnc,
+ HandlersRaw: []json.RawMessage{
+ caddyconfig.JSONModuleObject(subroute, "handler", "subroute", warnings),
+ },
+ Terminal: true, // only first matching site block should be evaluated
+ })
+ }
+ return routeList
+}
+
+// buildSubroute turns the config values, which are expected to be routes
+// into a clean and orderly subroute that has all the routes within it.
func buildSubroute(routes []ConfigValue, groupCounter counter) (*caddyhttp.Subroute, error) {
for _, val := range routes {
if !directiveIsOrdered(val.directive) {