summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--caddyconfig/httpcaddyfile/directives.go15
-rw-r--r--caddyconfig/httpcaddyfile/httptype.go22
-rw-r--r--caddyconfig/httpcaddyfile/options.go87
3 files changed, 85 insertions, 39 deletions
diff --git a/caddyconfig/httpcaddyfile/directives.go b/caddyconfig/httpcaddyfile/directives.go
index e74a3fe..b866c7d 100644
--- a/caddyconfig/httpcaddyfile/directives.go
+++ b/caddyconfig/httpcaddyfile/directives.go
@@ -25,9 +25,9 @@ import (
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
)
-// defaultDirectiveOrder specifies the order
+// directiveOrder specifies the order
// to apply directives in HTTP routes.
-var defaultDirectiveOrder = []string{
+var directiveOrder = []string{
"rewrite",
"strip_prefix",
"strip_suffix",
@@ -168,6 +168,8 @@ func (h Helper) NewRoute(matcherSet caddy.ModuleMap,
}
}
+// GroupRoutes adds the routes (caddyhttp.Route type) in vals to the
+// same group, if there is more than one route in vals.
func (h Helper) GroupRoutes(vals []ConfigValue) {
// ensure there's at least two routes; group of one is pointless
var count int
@@ -185,7 +187,7 @@ func (h Helper) GroupRoutes(vals []ConfigValue) {
// now that we know the group will have some effect, do it
groupNum := *h.groupCounter
- for i := 0; i < len(vals); i++ {
+ for i := range vals {
if route, ok := vals[i].Value.(caddyhttp.Route); ok {
route.Group = fmt.Sprintf("group%d", groupNum)
vals[i].Value = route
@@ -226,7 +228,12 @@ type ConfigValue struct {
directive string
}
-func sortRoutes(handlers []ConfigValue, dirPositions map[string]int) {
+func sortRoutes(handlers []ConfigValue) {
+ dirPositions := make(map[string]int)
+ for i, dir := range directiveOrder {
+ dirPositions[dir] = i
+ }
+
// while we are sorting, we will need to decode a route's path matcher
// in order to sub-sort by path length; we can amortize this operation
// for efficiency by storing the decoded matchers in a slice
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go
index 257e7be..6ed4e39 100644
--- a/caddyconfig/httpcaddyfile/httptype.go
+++ b/caddyconfig/httpcaddyfile/httptype.go
@@ -65,8 +65,8 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
val, err = parseOptHTTPPort(disp)
case "https_port":
val, err = parseOptHTTPSPort(disp)
- case "handler_order":
- val, err = parseOptHandlerOrder(disp)
+ case "order":
+ val, err = parseOptOrder(disp)
case "experimental_http3":
val, err = parseOptExperimentalHTTP3(disp)
case "storage":
@@ -397,23 +397,9 @@ func (st *ServerType) serversFromPairings(
siteSubroute.Routes = append(siteSubroute.Routes, cfgVal.Value.(caddyhttp.Route))
}
- // set up each handler directive - the order of the handlers
- // as they are added to the routes depends on user preference
+ // set up each handler directive, making sure to honor directive order
dirRoutes := sblock.pile["route"]
- handlerOrder, ok := options["handler_order"].([]string)
- if !ok {
- handlerOrder = defaultDirectiveOrder
- }
- if len(handlerOrder) == 1 && handlerOrder[0] == "appearance" {
- handlerOrder = nil
- }
- if handlerOrder != nil {
- dirPositions := make(map[string]int)
- for i, dir := range handlerOrder {
- dirPositions[dir] = i
- }
- sortRoutes(dirRoutes, dirPositions)
- }
+ sortRoutes(dirRoutes)
// add all the routes piled in from directives
for _, r := range dirRoutes {
diff --git a/caddyconfig/httpcaddyfile/options.go b/caddyconfig/httpcaddyfile/options.go
index e87b30f..e81528e 100644
--- a/caddyconfig/httpcaddyfile/options.go
+++ b/caddyconfig/httpcaddyfile/options.go
@@ -58,27 +58,80 @@ func parseOptExperimentalHTTP3(d *caddyfile.Dispenser) (bool, error) {
return true, nil
}
-func parseOptHandlerOrder(d *caddyfile.Dispenser) ([]string, error) {
- if !d.Next() {
- return nil, d.ArgErr()
- }
- order := d.RemainingArgs()
- if len(order) == 1 && order[0] == "appearance" {
- return []string{"appearance"}, nil
- }
- if len(order) > 0 && d.NextBlock(0) {
- return nil, d.Err("cannot open block if there are arguments")
- }
- for d.NextBlock(0) {
- order = append(order, d.Val())
+func parseOptOrder(d *caddyfile.Dispenser) ([]string, error) {
+ newOrder := directiveOrder
+
+ for d.Next() {
+ // get directive name
+ if !d.Next() {
+ return nil, d.ArgErr()
+ }
+ dirName := d.Val()
+ if _, ok := registeredDirectives[dirName]; !ok {
+ return nil, fmt.Errorf("%s is not a registered directive", dirName)
+ }
+
+ // get positional token
+ if !d.Next() {
+ return nil, d.ArgErr()
+ }
+ pos := d.Val()
+
+ // if directive exists, first remove it
+ for i, d := range newOrder {
+ if d == dirName {
+ newOrder = append(newOrder[:i], newOrder[i+1:]...)
+ break
+ }
+ }
+
+ // act on the positional
+ switch pos {
+ case "first":
+ newOrder = append([]string{dirName}, newOrder...)
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ directiveOrder = newOrder
+ return newOrder, nil
+ case "last":
+ newOrder = append(newOrder, dirName)
+ if d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ directiveOrder = newOrder
+ return newOrder, nil
+ case "before":
+ case "after":
+ default:
+ return nil, fmt.Errorf("unknown positional '%s'", pos)
+ }
+
+ // get name of other directive
+ if !d.NextArg() {
+ return nil, d.ArgErr()
+ }
+ otherDir := d.Val()
if d.NextArg() {
return nil, d.ArgErr()
}
+
+ // insert directive into proper position
+ for i, d := range newOrder {
+ if d == otherDir {
+ if pos == "before" {
+ newOrder = append(newOrder[:i], append([]string{dirName}, newOrder[i:]...)...)
+ } else if pos == "after" {
+ newOrder = append(newOrder[:i+1], append([]string{dirName}, newOrder[i+1:]...)...)
+ }
+ break
+ }
+ }
}
- if len(order) == 0 {
- return nil, d.ArgErr()
- }
- return order, nil
+
+ directiveOrder = newOrder
+
+ return newOrder, nil
}
func parseOptStorage(d *caddyfile.Dispenser) (caddy.StorageConverter, error) {