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