httpcaddyfile: Group try_files routes together (#2891)

This ensures that only the first matching route is used.
This commit is contained in:
Matthew Holt 2020-01-16 11:29:20 -07:00
parent a66f461201
commit 2466ed1484
No known key found for this signature in database
GPG Key ID: 2A349DD577D586A5
3 changed files with 44 additions and 9 deletions

View File

@ -16,6 +16,7 @@ package httpcaddyfile
import (
"encoding/json"
"fmt"
"sort"
"github.com/caddyserver/caddy/v2"
@ -93,10 +94,11 @@ func RegisterHandlerDirective(dir string, setupFunc UnmarshalHandlerFunc) {
// Caddyfile tokens.
type Helper struct {
*caddyfile.Dispenser
options map[string]interface{}
warnings *[]caddyconfig.Warning
matcherDefs map[string]caddy.ModuleMap
parentBlock caddyfile.ServerBlock
options map[string]interface{}
warnings *[]caddyconfig.Warning
matcherDefs map[string]caddy.ModuleMap
parentBlock caddyfile.ServerBlock
groupCounter *int
}
// Option gets the option keyed by name.
@ -166,6 +168,32 @@ func (h Helper) NewRoute(matcherSet caddy.ModuleMap,
}
}
func (h Helper) GroupRoutes(vals []ConfigValue) {
// ensure there's at least two routes; group of one is pointless
var count int
for _, v := range vals {
if _, ok := v.Value.(caddyhttp.Route); ok {
count++
if count > 1 {
break
}
}
}
if count < 2 {
return
}
// now that we know the group will have some effect, do it
groupNum := *h.groupCounter
for i := 0; i < len(vals); i++ {
if route, ok := vals[i].Value.(caddyhttp.Route); ok {
route.Group = fmt.Sprintf("group%d", groupNum)
vals[i].Value = route
}
}
*h.groupCounter++
}
// NewBindAddresses returns config values relevant to adding
// listener bind addresses to the config.
func (h Helper) NewBindAddresses(addrs []string) []ConfigValue {

View File

@ -41,6 +41,7 @@ type ServerType struct {
func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
options map[string]interface{}) (*caddy.Config, []caddyconfig.Warning, error) {
var warnings []caddyconfig.Warning
groupCounter := new(int)
var serverBlocks []serverBlock
for _, sblock := range originalServerBlocks {
@ -140,11 +141,12 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
}
results, err := dirFunc(Helper{
Dispenser: caddyfile.NewDispenser(segment),
options: options,
warnings: &warnings,
matcherDefs: matcherDefs,
parentBlock: sb.block,
Dispenser: caddyfile.NewDispenser(segment),
options: options,
warnings: &warnings,
matcherDefs: matcherDefs,
parentBlock: sb.block,
groupCounter: groupCounter,
})
if err != nil {
return nil, warnings, fmt.Errorf("parsing caddyfile tokens for '%s': %v", dir, err)

View File

@ -163,5 +163,10 @@ func parseTryFiles(h httpcaddyfile.Helper) ([]httpcaddyfile.ConfigValue, error)
result = append(result, makeRoute(try, "")...)
}
// ensure that multiple routes (possible if rewrite targets
// have query strings, for example) are grouped together
// so only the first matching rewrite is performed (#2891)
h.GroupRoutes(result)
return result, nil
}