Enables the use of elements declared in other providers
This commit is contained in:
parent
a79d6aa669
commit
8735263930
16 changed files with 753 additions and 94 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containous/alice"
|
||||
"github.com/containous/traefik/config"
|
||||
|
@ -26,9 +27,16 @@ import (
|
|||
"github.com/containous/traefik/middlewares/stripprefix"
|
||||
"github.com/containous/traefik/middlewares/stripprefixregex"
|
||||
"github.com/containous/traefik/middlewares/tracing"
|
||||
"github.com/containous/traefik/server/internal"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type middlewareStackType int
|
||||
|
||||
const (
|
||||
middlewareStackKey middlewareStackType = iota
|
||||
)
|
||||
|
||||
// Builder the middleware builder
|
||||
type Builder struct {
|
||||
configs map[string]*config.Middleware
|
||||
|
@ -45,22 +53,40 @@ func NewBuilder(configs map[string]*config.Middleware, serviceBuilder serviceBui
|
|||
}
|
||||
|
||||
// BuildChain creates a middleware chain
|
||||
func (b *Builder) BuildChain(ctx context.Context, middlewares []string) (*alice.Chain, error) {
|
||||
func (b *Builder) BuildChain(ctx context.Context, middlewares []string) *alice.Chain {
|
||||
chain := alice.New()
|
||||
for _, middlewareName := range middlewares {
|
||||
if _, ok := b.configs[middlewareName]; !ok {
|
||||
return nil, fmt.Errorf("middleware %q does not exist", middlewareName)
|
||||
}
|
||||
middlewareName := internal.GetQualifiedName(ctx, middlewareName)
|
||||
constructorContext := internal.AddProviderInContext(ctx, middlewareName)
|
||||
chain = chain.Append(func(next http.Handler) (http.Handler, error) {
|
||||
var err error
|
||||
if constructorContext, err = checkRecursivity(constructorContext, middlewareName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
constructor, err := b.buildConstructor(ctx, middlewareName, *b.configs[middlewareName])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if constructor != nil {
|
||||
chain = chain.Append(constructor)
|
||||
}
|
||||
if _, ok := b.configs[middlewareName]; !ok {
|
||||
return nil, fmt.Errorf("middleware %q does not exist", middlewareName)
|
||||
}
|
||||
|
||||
constructor, err := b.buildConstructor(constructorContext, middlewareName, *b.configs[middlewareName])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while instanciation of %s: %v", middlewareName, err)
|
||||
}
|
||||
return constructor(next)
|
||||
})
|
||||
}
|
||||
return &chain, nil
|
||||
return &chain
|
||||
}
|
||||
|
||||
func checkRecursivity(ctx context.Context, middlewareName string) (context.Context, error) {
|
||||
currentStack, ok := ctx.Value(middlewareStackKey).([]string)
|
||||
if !ok {
|
||||
currentStack = []string{}
|
||||
}
|
||||
if inSlice(middlewareName, currentStack) {
|
||||
return ctx, fmt.Errorf("could not instantiate middleware %s: recursion detected in %s", middlewareName, strings.Join(append(currentStack, middlewareName), "->"))
|
||||
}
|
||||
return context.WithValue(ctx, middlewareStackKey, append(currentStack, middlewareName)), nil
|
||||
}
|
||||
|
||||
func (b *Builder) buildConstructor(ctx context.Context, middlewareName string, config config.Middleware) (alice.Constructor, error) {
|
||||
|
@ -290,3 +316,12 @@ func (b *Builder) buildConstructor(ctx context.Context, middlewareName string, c
|
|||
|
||||
return tracing.Wrap(ctx, middleware), nil
|
||||
}
|
||||
|
||||
func inSlice(element string, stack []string) bool {
|
||||
for _, value := range stack {
|
||||
if value == element {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue