2019-08-26 10:20:06 +00:00
|
|
|
package middlewares
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
|
2022-11-21 17:36:05 +00:00
|
|
|
"github.com/rs/zerolog/log"
|
2020-09-16 13:46:04 +00:00
|
|
|
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
2022-11-21 17:36:05 +00:00
|
|
|
"github.com/vulcand/oxy/v2/utils"
|
2019-08-26 10:20:06 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// GetSourceExtractor returns the SourceExtractor function corresponding to the given sourceMatcher.
|
|
|
|
// It defaults to a RemoteAddrStrategy IPStrategy if need be.
|
2020-04-29 16:32:05 +00:00
|
|
|
// It returns an error if more than one source criterion is provided.
|
2019-08-26 10:20:06 +00:00
|
|
|
func GetSourceExtractor(ctx context.Context, sourceMatcher *dynamic.SourceCriterion) (utils.SourceExtractor, error) {
|
2020-04-29 16:32:05 +00:00
|
|
|
if sourceMatcher != nil {
|
|
|
|
if sourceMatcher.IPStrategy != nil && sourceMatcher.RequestHeaderName != "" {
|
|
|
|
return nil, errors.New("iPStrategy and RequestHeaderName are mutually exclusive")
|
|
|
|
}
|
|
|
|
if sourceMatcher.IPStrategy != nil && sourceMatcher.RequestHost {
|
|
|
|
return nil, errors.New("iPStrategy and RequestHost are mutually exclusive")
|
|
|
|
}
|
|
|
|
if sourceMatcher.RequestHeaderName != "" && sourceMatcher.RequestHost {
|
|
|
|
return nil, errors.New("requestHost and RequestHeaderName are mutually exclusive")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-26 10:20:06 +00:00
|
|
|
if sourceMatcher == nil ||
|
|
|
|
sourceMatcher.IPStrategy == nil &&
|
|
|
|
sourceMatcher.RequestHeaderName == "" && !sourceMatcher.RequestHost {
|
|
|
|
sourceMatcher = &dynamic.SourceCriterion{
|
|
|
|
IPStrategy: &dynamic.IPStrategy{},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-21 17:36:05 +00:00
|
|
|
logger := log.Ctx(ctx)
|
2019-08-26 10:20:06 +00:00
|
|
|
if sourceMatcher.IPStrategy != nil {
|
|
|
|
strategy, err := sourceMatcher.IPStrategy.Get()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-11-21 17:36:05 +00:00
|
|
|
logger.Debug().Msg("Using IPStrategy")
|
2019-08-26 10:20:06 +00:00
|
|
|
return utils.ExtractorFunc(func(req *http.Request) (string, int64, error) {
|
|
|
|
return strategy.GetIP(req), 1, nil
|
|
|
|
}), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if sourceMatcher.RequestHeaderName != "" {
|
2022-11-21 17:36:05 +00:00
|
|
|
logger.Debug().Msg("Using RequestHeaderName")
|
2019-08-26 10:20:06 +00:00
|
|
|
return utils.NewExtractor(fmt.Sprintf("request.header.%s", sourceMatcher.RequestHeaderName))
|
|
|
|
}
|
|
|
|
|
|
|
|
if sourceMatcher.RequestHost {
|
2022-11-21 17:36:05 +00:00
|
|
|
logger.Debug().Msg("Using RequestHost")
|
2019-08-26 10:20:06 +00:00
|
|
|
return utils.NewExtractor("request.host")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errors.New("no SourceCriterion criterion defined")
|
|
|
|
}
|