Refactor new muxer to have only one parser instance
This commit is contained in:
parent
55e6d327bc
commit
fa18c35a9a
13 changed files with 240 additions and 105 deletions
103
pkg/muxer/http/parser.go
Normal file
103
pkg/muxer/http/parser.go
Normal file
|
@ -0,0 +1,103 @@
|
|||
package http
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/traefik/traefik/v3/pkg/rules"
|
||||
"github.com/vulcand/predicate"
|
||||
)
|
||||
|
||||
type SyntaxParser struct {
|
||||
parsers map[string]*parser
|
||||
}
|
||||
|
||||
type Options func(map[string]matcherBuilderFuncs)
|
||||
|
||||
func WithMatcher(syntax, matcherName string, builderFunc func(params ...string) (MatcherFunc, error)) Options {
|
||||
return func(syntaxFuncs map[string]matcherBuilderFuncs) {
|
||||
syntax = strings.ToLower(syntax)
|
||||
|
||||
syntaxFuncs[syntax][matcherName] = func(tree *matchersTree, s ...string) error {
|
||||
matcher, err := builderFunc(s...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("building matcher: %w", err)
|
||||
}
|
||||
|
||||
tree.matcher = matcher
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewSyntaxParser(opts ...Options) (SyntaxParser, error) {
|
||||
syntaxFuncs := map[string]matcherBuilderFuncs{
|
||||
"v2": httpFuncsV2,
|
||||
"v3": httpFuncs,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(syntaxFuncs)
|
||||
}
|
||||
|
||||
parsers := map[string]*parser{}
|
||||
for syntax, funcs := range syntaxFuncs {
|
||||
var err error
|
||||
parsers[syntax], err = newParser(funcs)
|
||||
if err != nil {
|
||||
return SyntaxParser{}, err
|
||||
}
|
||||
}
|
||||
|
||||
return SyntaxParser{
|
||||
parsers: parsers,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s SyntaxParser) parse(syntax string, rule string) (matchersTree, error) {
|
||||
parser, ok := s.parsers[syntax]
|
||||
if !ok {
|
||||
parser = s.parsers["v3"]
|
||||
}
|
||||
|
||||
return parser.parse(rule)
|
||||
}
|
||||
|
||||
func newParser(funcs matcherBuilderFuncs) (*parser, error) {
|
||||
p, err := rules.NewParser(slices.Collect(maps.Keys(funcs)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &parser{
|
||||
parser: p,
|
||||
matcherFuncs: funcs,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type parser struct {
|
||||
parser predicate.Parser
|
||||
matcherFuncs matcherBuilderFuncs
|
||||
}
|
||||
|
||||
func (p *parser) parse(rule string) (matchersTree, error) {
|
||||
parse, err := p.parser.Parse(rule)
|
||||
if err != nil {
|
||||
return matchersTree{}, fmt.Errorf("parsing rule %s: %w", rule, err)
|
||||
}
|
||||
buildTree, ok := parse.(rules.TreeBuilder)
|
||||
if !ok {
|
||||
return matchersTree{}, errors.New("obtaining build tree")
|
||||
}
|
||||
|
||||
var matchers matchersTree
|
||||
err = matchers.addRule(buildTree(), p.matcherFuncs)
|
||||
if err != nil {
|
||||
return matchersTree{}, fmt.Errorf("adding rule %s: %w", rule, err)
|
||||
}
|
||||
|
||||
return matchers, nil
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue