github.com/hellofresh/janus@v0.0.0-20230925145208-ce8de8183c67/pkg/proxy/register.go (about) 1 package proxy 2 3 import ( 4 "fmt" 5 "net/http" 6 "strings" 7 "time" 8 9 "github.com/hellofresh/stats-go/client" 10 log "github.com/sirupsen/logrus" 11 "go.opencensus.io/plugin/ochttp" 12 13 "github.com/hellofresh/janus/pkg/proxy/balancer" 14 "github.com/hellofresh/janus/pkg/proxy/transport" 15 "github.com/hellofresh/janus/pkg/router" 16 ) 17 18 const ( 19 methodAll = "ALL" 20 ) 21 22 // Register handles the register of proxies into the chosen router. 23 // It also handles the conversion from a proxy to an http.HandlerFunc 24 type Register struct { 25 router router.Router 26 idleConnectionsPerHost int 27 idleConnTimeout time.Duration 28 idleConnPurgeTicker *time.Ticker 29 flushInterval time.Duration 30 statsClient client.Client 31 matcher *router.ListenPathMatcher 32 isPublicEndpoint bool 33 } 34 35 // NewRegister creates a new instance of Register 36 func NewRegister(opts ...RegisterOption) *Register { 37 r := Register{ 38 matcher: router.NewListenPathMatcher(), 39 } 40 41 for _, opt := range opts { 42 opt(&r) 43 } 44 45 return &r 46 } 47 48 // UpdateRouter updates the reference to the router. This is useful to reload the mux 49 func (p *Register) UpdateRouter(router router.Router) { 50 p.router = router 51 } 52 53 // Add register a new route 54 func (p *Register) Add(definition *RouterDefinition) error { 55 log.WithField("balancing_alg", definition.Upstreams.Balancing).Debug("Using a load balancing algorithm") 56 balancerInstance, err := balancer.New(definition.Upstreams.Balancing) 57 if err != nil { 58 log.WithError(err).Error("Could not create a balancer") 59 return fmt.Errorf("could not create a balancer: %w", err) 60 } 61 62 handler := NewBalancedReverseProxy(definition.Definition, balancerInstance, p.statsClient) 63 handler.FlushInterval = p.flushInterval 64 handler.Transport = &ochttp.Transport{ 65 Base: transport.New( 66 transport.WithIdleConnTimeout(p.idleConnTimeout), 67 transport.WithIdleConnPurgeTicker(p.idleConnPurgeTicker), 68 transport.WithInsecureSkipVerify(definition.InsecureSkipVerify), 69 transport.WithDialTimeout(time.Duration(definition.ForwardingTimeouts.DialTimeout)), 70 transport.WithResponseHeaderTimeout(time.Duration(definition.ForwardingTimeouts.ResponseHeaderTimeout)), 71 ), 72 } 73 74 if p.matcher.Match(definition.ListenPath) { 75 p.doRegister(p.matcher.Extract(definition.ListenPath), definition, &ochttp.Handler{Handler: handler, IsPublicEndpoint: p.isPublicEndpoint}) 76 } 77 78 p.doRegister(definition.ListenPath, definition, &ochttp.Handler{Handler: handler, IsPublicEndpoint: p.isPublicEndpoint}) 79 return nil 80 } 81 82 func (p *Register) doRegister(listenPath string, def *RouterDefinition, handler http.Handler) { 83 log.WithFields(log.Fields{ 84 "listen_path": listenPath, 85 }).Debug("Registering a route") 86 87 if strings.Index(listenPath, "/") != 0 { 88 log.WithField("listen_path", listenPath). 89 Error("Route listen path must begin with '/'. Skipping invalid route.") 90 } else { 91 for _, method := range def.Methods { 92 if strings.ToUpper(method) == methodAll { 93 p.router.Any(listenPath, handler.ServeHTTP, def.middleware...) 94 } else { 95 p.router.Handle(strings.ToUpper(method), listenPath, handler.ServeHTTP, def.middleware...) 96 } 97 } 98 } 99 }