traefik/rules/parser.go
SALLEYRON Julien 9ebe3c38b2 New rule syntax
Co-authored-by: jbdoumenjou <jb.doumenjou@gmail.com>
2019-01-30 16:24:07 +01:00

97 lines
1.8 KiB
Go

package rules
import (
"strings"
"github.com/pkg/errors"
"github.com/vulcand/predicate"
)
type treeBuilder func() *tree
// ParseDomains extract domains from rule
func ParseDomains(rule string) ([]string, error) {
parser, err := newParser()
if err != nil {
return nil, err
}
parse, err := parser.Parse(rule)
if err != nil {
return nil, err
}
buildTree, ok := parse.(treeBuilder)
if !ok {
return nil, errors.New("cannot parse")
}
return lower(parseDomain(buildTree())), nil
}
func lower(slice []string) []string {
var lowerStrings []string
for _, value := range slice {
lowerStrings = append(lowerStrings, strings.ToLower(value))
}
return lowerStrings
}
func parseDomain(tree *tree) []string {
switch tree.matcher {
case "and", "or":
return append(parseDomain(tree.ruleLeft), parseDomain(tree.ruleRight)...)
case "Host":
return tree.value
default:
return nil
}
}
func andFunc(left, right treeBuilder) treeBuilder {
return func() *tree {
return &tree{
matcher: "and",
ruleLeft: left(),
ruleRight: right(),
}
}
}
func orFunc(left, right treeBuilder) treeBuilder {
return func() *tree {
return &tree{
matcher: "or",
ruleLeft: left(),
ruleRight: right(),
}
}
}
func newParser() (predicate.Parser, error) {
parserFuncs := make(map[string]interface{})
for matcherName := range funcs {
matcherName := matcherName
fn := func(value ...string) treeBuilder {
return func() *tree {
return &tree{
matcher: matcherName,
value: value,
}
}
}
parserFuncs[matcherName] = fn
parserFuncs[strings.ToLower(matcherName)] = fn
parserFuncs[strings.ToUpper(matcherName)] = fn
parserFuncs[strings.Title(strings.ToLower(matcherName))] = fn
}
return predicate.NewParser(predicate.Def{
Operators: predicate.Operators{
AND: andFunc,
OR: orFunc,
},
Functions: parserFuncs,
})
}