Skip to content

Commit

Permalink
fix linting issues
Browse files Browse the repository at this point in the history
  • Loading branch information
David Christofas committed Aug 30, 2022
1 parent 01780de commit 46f48de
Showing 1 changed file with 89 additions and 79 deletions.
168 changes: 89 additions & 79 deletions services/proxy/pkg/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ import (
"go-micro.dev/v4/selector"
)

const routingInfoCtxKey string = "director"
type routingInfoCtxKey struct{}

var noInfo = RoutingInfo{}

// Middleware returns a HTTP middleware containing the router.
func Middleware(policySelector *config.PolicySelector, policies []config.Policy, logger log.Logger) func(http.Handler) http.Handler {
router := New(policySelector, policies, logger)
return func(next http.Handler) http.Handler {
Expand All @@ -32,70 +33,8 @@ func Middleware(policySelector *config.PolicySelector, policies []config.Policy,
}
}

func (rt Router) Route(r *http.Request) (RoutingInfo, bool) {
pol, err := rt.policySelector(r)
if err != nil {
rt.logger.Error().Err(err).Msg("Error while selecting pol")
return noInfo, false
}

if _, ok := rt.directors[pol]; !ok {
rt.logger.
Error().
Str("policy", pol).
Msg("policy is not configured")
return noInfo, false
}

method := ""
// find matching director
for _, rtype := range config.RouteTypes {
var handler func(string, url.URL) bool
switch rtype {
case config.QueryRoute:
handler = queryRouteMatcher
case config.RegexRoute:
handler = rt.regexRouteMatcher
case config.PrefixRoute:
fallthrough
default:
handler = prefixRouteMatcher
}
if rt.directors[pol][rtype][r.Method] != nil {
// use specific method
method = r.Method
}
for endpoint := range rt.directors[pol][rtype][method] {
if handler(endpoint, *r.URL) {

rt.logger.Debug().
Str("policy", pol).
Str("method", r.Method).
Str("prefix", endpoint).
Str("path", r.URL.Path).
Str("routeType", string(rtype)).
Msg("director found")

return rt.directors[pol][rtype][method][endpoint], true
}
}
}

// override default director with root. If any
if ri, ok := rt.directors[pol][config.PrefixRoute][method]["/"]; ok { // try specific method
return ri, true
} else if ri, ok := rt.directors[pol][config.PrefixRoute][""]["/"]; ok { // fallback to unspecific method
return ri, true
}

rt.logger.
Warn().
Str("policy", pol).
Str("path", r.URL.Path).
Msg("no director found")
return noInfo, false
}

// New creates a new request router.
// It initializes the routes before returning the router.
func New(policySelector *config.PolicySelector, policies []config.Policy, logger log.Logger) Router {
if policySelector == nil {
firstPolicy := policies[0].Name
Expand Down Expand Up @@ -143,19 +82,23 @@ func New(policySelector *config.PolicySelector, policies []config.Policy, logger
return r
}

// RoutingInfo contains the proxy director and some information about the route.
type RoutingInfo struct {
director func(*http.Request)
unprotected bool
}

// Director returns the proxy director.
func (r RoutingInfo) Director() func(*http.Request) {
return r.director
}

// IsRouteUnprotected returns true if the route doesn't need to be authenticated.
func (r RoutingInfo) IsRouteUnprotected() bool {
return r.unprotected
}

// Router handles the routing of HTTP requests according to the given policies.
type Router struct {
logger log.Logger
directors map[string]map[config.RouteType]map[string]map[string]RoutingInfo
Expand Down Expand Up @@ -227,6 +170,84 @@ func (rt Router) addHost(policy string, target *url.URL, route config.Route) {
},
}
}

// Route is evaluating the policies on the request and returns the RoutingInfo if successful.
func (rt Router) Route(r *http.Request) (RoutingInfo, bool) {
pol, err := rt.policySelector(r)
if err != nil {
rt.logger.Error().Err(err).Msg("Error while selecting pol")
return noInfo, false
}

if _, ok := rt.directors[pol]; !ok {
rt.logger.
Error().
Str("policy", pol).
Msg("policy is not configured")
return noInfo, false
}

method := ""
// find matching director
for _, rtype := range config.RouteTypes {
var handler func(string, url.URL) bool
switch rtype {
case config.QueryRoute:
handler = queryRouteMatcher
case config.RegexRoute:
handler = rt.regexRouteMatcher
case config.PrefixRoute:
fallthrough
default:
handler = prefixRouteMatcher
}
if rt.directors[pol][rtype][r.Method] != nil {
// use specific method
method = r.Method
}
for endpoint := range rt.directors[pol][rtype][method] {
if handler(endpoint, *r.URL) {

rt.logger.Debug().
Str("policy", pol).
Str("method", r.Method).
Str("prefix", endpoint).
Str("path", r.URL.Path).
Str("routeType", string(rtype)).
Msg("director found")

return rt.directors[pol][rtype][method][endpoint], true
}
}
}

// override default director with root. If any
if ri, ok := rt.directors[pol][config.PrefixRoute][method]["/"]; ok { // try specific method
return ri, true
} else if ri, ok := rt.directors[pol][config.PrefixRoute][""]["/"]; ok { // fallback to unspecific method
return ri, true
}

rt.logger.
Warn().
Str("policy", pol).
Str("path", r.URL.Path).
Msg("no director found")
return noInfo, false
}

func (rt Router) regexRouteMatcher(pattern string, target url.URL) bool {
matched, err := regexp.MatchString(pattern, target.String())
if err != nil {
rt.logger.Warn().Err(err).Str("pattern", pattern).Msg("regex with pattern failed")
}
return matched
}

func prefixRouteMatcher(prefix string, target url.URL) bool {
return strings.HasPrefix(target.Path, prefix) && prefix != "/"
}

func singleJoiningSlash(a, b string) string {
aslash := strings.HasSuffix(a, "/")
bslash := strings.HasPrefix(b, "/")
Expand Down Expand Up @@ -257,24 +278,13 @@ func queryRouteMatcher(endpoint string, target url.URL) bool {
return true
}

func (rt Router) regexRouteMatcher(pattern string, target url.URL) bool {
matched, err := regexp.MatchString(pattern, target.String())
if err != nil {
rt.logger.Warn().Err(err).Str("pattern", pattern).Msg("regex with pattern failed")
}
return matched
}

func prefixRouteMatcher(prefix string, target url.URL) bool {
return strings.HasPrefix(target.Path, prefix) && prefix != "/"
}

// SetRoutingInfo puts the routing info in the context.
func SetRoutingInfo(parent context.Context, ri RoutingInfo) context.Context {
return context.WithValue(parent, routingInfoCtxKey, ri)
return context.WithValue(parent, routingInfoCtxKey{}, ri)
}

// ContextRoutingInfo gets the routing information from the context.
func ContextRoutingInfo(ctx context.Context) RoutingInfo {
val := ctx.Value(routingInfoCtxKey)
val := ctx.Value(routingInfoCtxKey{})
return val.(RoutingInfo)
}

0 comments on commit 46f48de

Please sign in to comment.