caddyfile: Allow handler order to be customized

This commit is contained in:
Matthew Holt 2019-08-22 14:26:33 -06:00
parent af25f0254e
commit e34ff21a71
No known key found for this signature in database
GPG key ID: 2A349DD577D586A5
2 changed files with 42 additions and 10 deletions

View file

@ -66,6 +66,8 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
val, err = parseHTTPPort(caddyfile.NewDispenser(segment)) val, err = parseHTTPPort(caddyfile.NewDispenser(segment))
case "https_port": case "https_port":
val, err = parseHTTPSPort(caddyfile.NewDispenser(segment)) val, err = parseHTTPSPort(caddyfile.NewDispenser(segment))
case "handler_order":
val, err = parseHandlerOrder(caddyfile.NewDispenser(segment))
default: default:
return nil, warnings, fmt.Errorf("unrecognized parameter name: %s", dir) return nil, warnings, fmt.Errorf("unrecognized parameter name: %s", dir)
} }
@ -148,7 +150,7 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
// each pairing of listener addresses to list of server // each pairing of listener addresses to list of server
// blocks is basically a server definition // blocks is basically a server definition
servers, err := st.serversFromPairings(pairings, &warnings) servers, err := st.serversFromPairings(pairings, options, &warnings)
if err != nil { if err != nil {
return nil, warnings, err return nil, warnings, err
} }
@ -230,7 +232,11 @@ func (st *ServerType) hostsFromServerBlockKeys(sb caddyfile.ServerBlock) ([]stri
// serversFromPairings creates the servers for each pairing of addresses // serversFromPairings creates the servers for each pairing of addresses
// to server blocks. Each pairing is essentially a server definition. // to server blocks. Each pairing is essentially a server definition.
func (st *ServerType) serversFromPairings(pairings []sbAddrAssociation, warnings *[]caddyconfig.Warning) (map[string]*caddyhttp.Server, error) { func (st *ServerType) serversFromPairings(
pairings []sbAddrAssociation,
options map[string]interface{},
warnings *[]caddyconfig.Warning,
) (map[string]*caddyhttp.Server, error) {
servers := make(map[string]*caddyhttp.Server) servers := make(map[string]*caddyhttp.Server)
for i, p := range pairings { for i, p := range pairings {
@ -289,16 +295,19 @@ func (st *ServerType) serversFromPairings(pairings []sbAddrAssociation, warnings
siteVarSubroute.Routes = append(siteVarSubroute.Routes, cfgVal.Value.(caddyhttp.Route)) siteVarSubroute.Routes = append(siteVarSubroute.Routes, cfgVal.Value.(caddyhttp.Route))
} }
// set up each handler directive // set up each handler directive - the order of the handlers
// as they are added to the routes depends on user preference
dirRoutes := sblock.pile["route"] dirRoutes := sblock.pile["route"]
// TODO: The ordering here depends on... if there is a list of handlerOrder, ok := options["handler_order"].([]string)
// directives to use, then sort by that, otherwise just use in if !ok {
// the order they appear in the slice (which is the order they handlerOrder = defaultDirectiveOrder
// appeared in the Caddyfile) }
sortByList := true if len(handlerOrder) == 1 && handlerOrder[0] == "appearance" {
if sortByList { handlerOrder = nil
}
if handlerOrder != nil {
dirPositions := make(map[string]int) dirPositions := make(map[string]int)
for i, dir := range defaultDirectiveOrder { for i, dir := range handlerOrder {
dirPositions[dir] = i dirPositions[dir] = i
} }
sort.SliceStable(dirRoutes, func(i, j int) bool { sort.SliceStable(dirRoutes, func(i, j int) bool {

View file

@ -51,3 +51,26 @@ func parseHTTPSPort(d *caddyfile.Dispenser) (int, error) {
} }
return httpsPort, nil return httpsPort, nil
} }
func parseHandlerOrder(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() {
return nil, d.Err("cannot open block if there are arguments")
}
for d.NextBlock() {
order = append(order, d.Val())
if d.NextArg() {
return nil, d.ArgErr()
}
}
if len(order) == 0 {
return nil, d.ArgErr()
}
return order, nil
}