Beispiel #1
0
func (server *Server) prepareServer(router *mux.Router, entryPoint *EntryPoint, oldServer *manners.GracefulServer, middlewares ...negroni.Handler) (*manners.GracefulServer, error) {
	log.Info("Preparing server")
	// middlewares
	var negroni = negroni.New()
	for _, middleware := range middlewares {
		negroni.Use(middleware)
	}
	negroni.UseHandler(router)
	tlsConfig, err := server.createTLSConfig(entryPoint.TLS)
	if err != nil {
		log.Fatalf("Error creating TLS config %s", err)
		return nil, err
	}

	if oldServer == nil {
		return manners.NewWithServer(
			&http.Server{
				Addr:      entryPoint.Address,
				Handler:   negroni,
				TLSConfig: tlsConfig,
			}), nil
	}
	gracefulServer, err := oldServer.HijackListener(&http.Server{
		Addr:      entryPoint.Address,
		Handler:   negroni,
		TLSConfig: tlsConfig,
	}, tlsConfig)
	if err != nil {
		log.Fatalf("Error hijacking server %s", err)
		return nil, err
	}
	return gracefulServer, nil
}
Beispiel #2
0
func prepareServer(router *mux.Router, globalConfiguration *GlobalConfiguration, oldServer *manners.GracefulServer, middlewares ...negroni.Handler) (*manners.GracefulServer, error) {
	log.Info("Preparing server")
	// middlewares
	var negroni = negroni.New()
	for _, middleware := range middlewares {
		negroni.Use(middleware)
	}
	negroni.UseHandler(router)
	tlsConfig, err := createTLSConfig(globalConfiguration.Certificates)
	if err != nil {
		log.Fatalf("Error creating TLS config %s", err)
		return nil, err
	}

	if oldServer == nil {
		return manners.NewWithServer(
			&http.Server{
				Addr:      globalConfiguration.Port,
				Handler:   negroni,
				TLSConfig: tlsConfig,
			}), nil
	}
	server, err := oldServer.HijackListener(&http.Server{
		Addr:      globalConfiguration.Port,
		Handler:   negroni,
		TLSConfig: tlsConfig,
	}, tlsConfig)
	if err != nil {
		log.Fatalf("Error hijacking server %s", err)
		return nil, err
	}
	return server, nil
}
Beispiel #3
0
func prepareServer(router *mux.Router, globalConfiguration *GlobalConfiguration, oldServer *manners.GracefulServer, middlewares ...negroni.Handler) *manners.GracefulServer {
	log.Info("Preparing server")
	// middlewares
	var negroni = negroni.New()
	for _, middleware := range middlewares {
		negroni.Use(middleware)
	}
	negroni.UseHandler(router)

	if oldServer == nil {
		return manners.NewWithServer(
			&http.Server{
				Addr:    globalConfiguration.Port,
				Handler: negroni,
			})
	} else {
		server, err := oldServer.HijackListener(&http.Server{
			Addr:    globalConfiguration.Port,
			Handler: negroni,
		}, nil)
		if err != nil {
			log.Fatalf("Error hijacking server %s", err)
			return nil
		} else {
			return server
		}
	}
}
Beispiel #4
0
func main() {
	c := cors.New(cors.Options{
		AllowedOrigins: []string{"http://localhost:5000"},
	})

	fmt.Printf("milestone api activated on port :4000\n\r")
	services.SetupRabbitMq()

	router := routes.InitRoutes()
	negroni := negroni.Classic()
	negroni.Use(c)
	negroni.UseHandler(router)
	negroni.Run(":4400")
	//http.ListenAndServe(":4400", router)

}
Beispiel #5
0
// initNegroni initializes Negroni with all the middleware and starts it.
func initNegroni(routes Routes, config ServiceConfig) (*RestServiceInfo, error) {
	var err error
	// Create negroni
	negroni := negroni.New()

	// Add content-negotiation middleware.
	// This is an example of using a middleware.
	// This will modify the response header to the
	// negotiated content type, and can then be used as
	// ct := w.Header().Get("Content-Type")
	// where w is http.ResponseWriter
	negroni.Use(NewNegotiator())
	// Unmarshal data from the content-type format
	// into a map
	negroni.Use(NewUnmarshaller())
	pubKeyLocation := config.Common.Api.AuthPublic
	if pubKeyLocation != "" {
		log.Infof("Reading public key from %s", pubKeyLocation)
		config.Common.PublicKey, err = ioutil.ReadFile(pubKeyLocation)
	}
	if err != nil {
		return nil, err
	}
	// We use the public key of root server to check the token.
	authMiddleware := AuthMiddleware{PublicKey: config.Common.PublicKey}
	negroni.Use(authMiddleware)

	timeoutMillis := getTimeoutMillis(config.Common)
	var dur time.Duration
	var readWriteDur time.Duration
	timeoutStr := fmt.Sprintf("%dms", timeoutMillis)
	dur, _ = time.ParseDuration(timeoutStr)
	timeoutStr = fmt.Sprintf("%dms", timeoutMillis+ReadWriteTimeoutDelta)
	readWriteDur, _ = time.ParseDuration(timeoutStr)

	router := newRouter(routes)
	timeoutHandler := http.TimeoutHandler(router, dur, TimeoutMessage)
	negroni.UseHandler(timeoutHandler)

	hostPort := config.Common.Api.GetHostPort()
	svcInfo, err := RunNegroni(negroni, hostPort, readWriteDur)
	return svcInfo, err
}
Beispiel #6
0
// LoadConfig returns a new gorrilla.mux Route from the specified global configuration and the dynamic
// provider configurations.
func LoadConfig(configurations configs, globalConfiguration *GlobalConfiguration) (*mux.Router, error) {
	router := mux.NewRouter()
	router.NotFoundHandler = http.HandlerFunc(notFoundHandler)
	backends := map[string]http.Handler{}
	for _, configuration := range configurations {
		for frontendName, frontend := range configuration.Frontends {
			log.Debugf("Creating frontend %s", frontendName)
			fwd, _ := forward.New(forward.Logger(oxyLogger), forward.PassHostHeader(frontend.PassHostHeader))
			newRoute := router.NewRoute().Name(frontendName)
			for routeName, route := range frontend.Routes {
				log.Debugf("Creating route %s %s:%s", routeName, route.Rule, route.Value)
				newRouteReflect, err := invoke(newRoute, route.Rule, route.Value)
				if err != nil {
					return nil, err
				}
				newRoute = newRouteReflect[0].Interface().(*mux.Route)
			}
			if backends[frontend.Backend] == nil {
				log.Debugf("Creating backend %s", frontend.Backend)
				var lb http.Handler
				rr, _ := roundrobin.New(fwd)
				if configuration.Backends[frontend.Backend] == nil {
					return nil, errors.New("Backend not found: " + frontend.Backend)
				}
				lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
				if err != nil {
					configuration.Backends[frontend.Backend].LoadBalancer = &types.LoadBalancer{Method: "wrr"}
				}
				switch lbMethod {
				case types.Drr:
					log.Infof("Creating load-balancer drr")
					rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
					lb = rebalancer
					for serverName, server := range configuration.Backends[frontend.Backend].Servers {
						url, err := url.Parse(server.URL)
						if err != nil {
							return nil, err
						}
						log.Infof("Creating server %s %s", serverName, url.String())
						rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight))
					}
				case types.Wrr:
					log.Infof("Creating load-balancer wrr")
					lb = middlewares.NewWebsocketUpgrader(rr)
					for serverName, server := range configuration.Backends[frontend.Backend].Servers {
						url, err := url.Parse(server.URL)
						if err != nil {
							return nil, err
						}
						log.Infof("Creating server %s %s", serverName, url.String())
						rr.UpsertServer(url, roundrobin.Weight(server.Weight))
					}
				}
				var negroni = negroni.New()
				if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
					log.Infof("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
					negroni.Use(middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger)))
				} else {
					negroni.UseHandler(lb)
				}
				backends[frontend.Backend] = negroni
			} else {
				log.Infof("Reusing backend %s", frontend.Backend)
			}
			//		stream.New(backends[frontend.Backend], stream.Retry("IsNetworkError() && Attempts() <= " + strconv.Itoa(globalConfiguration.Replay)), stream.Logger(oxyLogger))

			newRoute.Handler(backends[frontend.Backend])
			err := newRoute.GetError()
			if err != nil {
				log.Errorf("Error building route: %s", err)
			}
		}
	}
	return router, nil
}
Beispiel #7
0
func main() {
	router := routers.InitRoutes()
	negroni := negroni.Classic()
	negroni.UseHandler(router)
	http.ListenAndServe(":4000", router)
}
Beispiel #8
0
// LoadConfig returns a new gorilla.mux Route from the specified global configuration and the dynamic
// provider configurations.
func (server *Server) loadConfig(configurations configs, globalConfiguration GlobalConfiguration) (map[string]serverEntryPoint, error) {
	serverEntryPoints := server.buildEntryPoints(globalConfiguration)
	redirectHandlers := make(map[string]http.Handler)

	backends := map[string]http.Handler{}
	for _, configuration := range configurations {
		frontendNames := sortedFrontendNamesForConfig(configuration)
		for _, frontendName := range frontendNames {
			frontend := configuration.Frontends[frontendName]

			log.Debugf("Creating frontend %s", frontendName)
			fwd, _ := forward.New(forward.Logger(oxyLogger), forward.PassHostHeader(frontend.PassHostHeader))
			// default endpoints if not defined in frontends
			if len(frontend.EntryPoints) == 0 {
				frontend.EntryPoints = globalConfiguration.DefaultEntryPoints
			}
			for _, entryPointName := range frontend.EntryPoints {
				log.Debugf("Wiring frontend %s to entryPoint %s", frontendName, entryPointName)
				if _, ok := serverEntryPoints[entryPointName]; !ok {
					return nil, errors.New("Undefined entrypoint: " + entryPointName)
				}
				newRoute := serverEntryPoints[entryPointName].httpRouter.NewRoute().Name(frontendName)
				for routeName, route := range frontend.Routes {
					log.Debugf("Creating route %s %s:%s", routeName, route.Rule, route.Value)
					route, err := getRoute(newRoute, route.Rule, route.Value)
					if err != nil {
						return nil, err
					}
					newRoute = route
				}
				entryPoint := globalConfiguration.EntryPoints[entryPointName]
				if entryPoint.Redirect != nil {
					if redirectHandlers[entryPointName] != nil {
						newRoute.Handler(redirectHandlers[entryPointName])
					} else if handler, err := server.loadEntryPointConfig(entryPointName, entryPoint); err != nil {
						return nil, err
					} else {
						newRoute.Handler(handler)
						redirectHandlers[entryPointName] = handler
					}
				} else {
					if backends[frontend.Backend] == nil {
						log.Debugf("Creating backend %s", frontend.Backend)
						var lb http.Handler
						rr, _ := roundrobin.New(fwd)
						if configuration.Backends[frontend.Backend] == nil {
							return nil, errors.New("Undefined backend: " + frontend.Backend)
						}
						lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
						if err != nil {
							configuration.Backends[frontend.Backend].LoadBalancer = &types.LoadBalancer{Method: "wrr"}
						}
						switch lbMethod {
						case types.Drr:
							log.Debugf("Creating load-balancer drr")
							rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
							lb = rebalancer
							for serverName, server := range configuration.Backends[frontend.Backend].Servers {
								url, err := url.Parse(server.URL)
								if err != nil {
									return nil, err
								}
								log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
								rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight))
							}
						case types.Wrr:
							log.Debugf("Creating load-balancer wrr")
							lb = middlewares.NewWebsocketUpgrader(rr)
							for serverName, server := range configuration.Backends[frontend.Backend].Servers {
								url, err := url.Parse(server.URL)
								if err != nil {
									return nil, err
								}
								log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
								rr.UpsertServer(url, roundrobin.Weight(server.Weight))
							}
						}
						var negroni = negroni.New()
						if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
							log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
							negroni.Use(middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger)))
						} else {
							negroni.UseHandler(lb)
						}
						backends[frontend.Backend] = negroni
					} else {
						log.Debugf("Reusing backend %s", frontend.Backend)
					}
					server.wireFrontendBackend(frontend.Routes, newRoute, backends[frontend.Backend])
				}
				err := newRoute.GetError()
				if err != nil {
					log.Errorf("Error building route: %s", err)
				}
			}
		}
	}
	return serverEntryPoints, nil
}
Beispiel #9
0
// LoadConfig returns a new gorilla.mux Route from the specified global configuration and the dynamic
// provider configurations.
func (server *Server) loadConfig(configurations configs, globalConfiguration GlobalConfiguration) (map[string]*serverEntryPoint, error) {
	serverEntryPoints := server.buildEntryPoints(globalConfiguration)
	redirectHandlers := make(map[string]http.Handler)

	backends := map[string]http.Handler{}
	backend2FrontendMap := map[string]string{}
	for _, configuration := range configurations {
		frontendNames := sortedFrontendNamesForConfig(configuration)
	frontend:
		for _, frontendName := range frontendNames {
			frontend := configuration.Frontends[frontendName]

			log.Debugf("Creating frontend %s", frontendName)

			fwd, err := forward.New(forward.Logger(oxyLogger), forward.PassHostHeader(frontend.PassHostHeader))
			if err != nil {
				log.Errorf("Error creating forwarder for frontend %s: %v", frontendName, err)
				log.Errorf("Skipping frontend %s...", frontendName)
				continue frontend
			}
			saveBackend := middlewares.NewSaveBackend(fwd)
			if len(frontend.EntryPoints) == 0 {
				log.Errorf("No entrypoint defined for frontend %s, defaultEntryPoints:%s", frontendName, globalConfiguration.DefaultEntryPoints)
				log.Errorf("Skipping frontend %s...", frontendName)
				continue frontend
			}
			for _, entryPointName := range frontend.EntryPoints {
				log.Debugf("Wiring frontend %s to entryPoint %s", frontendName, entryPointName)
				if _, ok := serverEntryPoints[entryPointName]; !ok {
					log.Errorf("Undefined entrypoint '%s' for frontend %s", entryPointName, frontendName)
					log.Errorf("Skipping frontend %s...", frontendName)
					continue frontend
				}
				newServerRoute := &serverRoute{route: serverEntryPoints[entryPointName].httpRouter.GetHandler().NewRoute().Name(frontendName)}
				for routeName, route := range frontend.Routes {
					err := getRoute(newServerRoute, &route)
					if err != nil {
						log.Errorf("Error creating route for frontend %s: %v", frontendName, err)
						log.Errorf("Skipping frontend %s...", frontendName)
						continue frontend
					}
					log.Debugf("Creating route %s %s", routeName, route.Rule)
				}
				entryPoint := globalConfiguration.EntryPoints[entryPointName]
				if entryPoint.Redirect != nil {
					if redirectHandlers[entryPointName] != nil {
						newServerRoute.route.Handler(redirectHandlers[entryPointName])
					} else if handler, err := server.loadEntryPointConfig(entryPointName, entryPoint); err != nil {
						log.Errorf("Error loading entrypoint configuration for frontend %s: %v", frontendName, err)
						log.Errorf("Skipping frontend %s...", frontendName)
						continue frontend
					} else {
						newServerRoute.route.Handler(handler)
						redirectHandlers[entryPointName] = handler
					}
				} else {
					if backends[frontend.Backend] == nil {
						log.Debugf("Creating backend %s", frontend.Backend)
						var lb http.Handler
						rr, _ := roundrobin.New(saveBackend)
						if configuration.Backends[frontend.Backend] == nil {
							log.Errorf("Undefined backend '%s' for frontend %s", frontend.Backend, frontendName)
							log.Errorf("Skipping frontend %s...", frontendName)
							continue frontend
						}

						lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
						if err != nil {
							log.Errorf("Error loading load balancer method '%+v' for frontend %s: %v", configuration.Backends[frontend.Backend].LoadBalancer, frontendName, err)
							log.Errorf("Skipping frontend %s...", frontendName)
							continue frontend
						}

						stickysession := configuration.Backends[frontend.Backend].LoadBalancer.Sticky
						cookiename := "_TRAEFIK_BACKEND"
						var sticky *roundrobin.StickySession

						if stickysession {
							sticky = roundrobin.NewStickySession(cookiename)
						}

						switch lbMethod {
						case types.Drr:
							log.Debugf("Creating load-balancer drr")
							rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
							if stickysession {
								log.Debugf("Sticky session with cookie %v", cookiename)
								rebalancer, _ = roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger), roundrobin.RebalancerStickySession(sticky))
							}
							lb = rebalancer
							for serverName, server := range configuration.Backends[frontend.Backend].Servers {
								url, err := url.Parse(server.URL)
								if err != nil {
									log.Errorf("Error parsing server URL %s: %v", server.URL, err)
									log.Errorf("Skipping frontend %s...", frontendName)
									continue frontend
								}
								backend2FrontendMap[url.String()] = frontendName
								log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
								if err := rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
									log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
									log.Errorf("Skipping frontend %s...", frontendName)
									continue frontend
								}
							}
						case types.Wrr:
							log.Debugf("Creating load-balancer wrr")
							if stickysession {
								log.Debugf("Sticky session with cookie %v", cookiename)
								rr, _ = roundrobin.New(saveBackend, roundrobin.EnableStickySession(sticky))
							}
							lb = rr
							for serverName, server := range configuration.Backends[frontend.Backend].Servers {
								url, err := url.Parse(server.URL)
								if err != nil {
									log.Errorf("Error parsing server URL %s: %v", server.URL, err)
									log.Errorf("Skipping frontend %s...", frontendName)
									continue frontend
								}
								backend2FrontendMap[url.String()] = frontendName
								log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
								if err := rr.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
									log.Errorf("Error adding server %s to load balancer: %v", server.URL, err)
									log.Errorf("Skipping frontend %s...", frontendName)
									continue frontend
								}
							}
						}
						maxConns := configuration.Backends[frontend.Backend].MaxConn
						if maxConns != nil && maxConns.Amount != 0 {
							extractFunc, err := utils.NewExtractor(maxConns.ExtractorFunc)
							if err != nil {
								log.Errorf("Error creating connlimit: %v", err)
								log.Errorf("Skipping frontend %s...", frontendName)
								continue frontend
							}
							log.Debugf("Creating loadd-balancer connlimit")
							lb, err = connlimit.New(lb, extractFunc, maxConns.Amount, connlimit.Logger(oxyLogger))
							if err != nil {
								log.Errorf("Error creating connlimit: %v", err)
								log.Errorf("Skipping frontend %s...", frontendName)
								continue frontend
							}
						}
						// retry ?
						if globalConfiguration.Retry != nil {
							retries := len(configuration.Backends[frontend.Backend].Servers)
							if globalConfiguration.Retry.Attempts > 0 {
								retries = globalConfiguration.Retry.Attempts
							}
							lb = middlewares.NewRetry(retries, lb)
							log.Debugf("Creating retries max attempts %d", retries)
						}

						var negroni = negroni.New()
						if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
							log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
							cbreaker, err := middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger))
							if err != nil {
								log.Errorf("Error creating circuit breaker: %v", err)
								log.Errorf("Skipping frontend %s...", frontendName)
								continue frontend
							}
							negroni.Use(cbreaker)
						} else {
							negroni.UseHandler(lb)
						}
						backends[frontend.Backend] = negroni
					} else {
						log.Debugf("Reusing backend %s", frontend.Backend)
					}
					if frontend.Priority > 0 {
						newServerRoute.route.Priority(frontend.Priority)
					}
					server.wireFrontendBackend(newServerRoute, backends[frontend.Backend])
				}
				err := newServerRoute.route.GetError()
				if err != nil {
					log.Errorf("Error building route: %s", err)
				}
			}
		}
	}
	middlewares.SetBackend2FrontendMap(&backend2FrontendMap)
	//sort routes
	for _, serverEntryPoint := range serverEntryPoints {
		serverEntryPoint.httpRouter.GetHandler().SortRoutes()
	}
	return serverEntryPoints, nil
}
Beispiel #10
0
func main() {
	kingpin.Parse()
	fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
	var srv *graceful.Server
	var configurationRouter *mux.Router
	var configurationChan = make(chan *Configuration, 10)
	defer close(configurationChan)
	var providers = []Provider{}
	var format = logging.MustStringFormatter("%{color}%{time:15:04:05.000} %{shortfile:20.20s} %{level:8.8s} %{id:03x} ▶%{color:reset} %{message}")
	var sigs = make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	// load global configuration
	gloablConfiguration := LoadFileConfig(*globalConfigFile)

	loggerMiddleware := middlewares.NewLogger(gloablConfiguration.AccessLogsFile)
	defer loggerMiddleware.Close()

	// logging
	backends := []logging.Backend{}
	level, err := logging.LogLevel(gloablConfiguration.LogLevel)
	if err != nil {
		log.Fatal("Error getting level", err)
	}

	if len(gloablConfiguration.TraefikLogsFile) > 0 {
		fi, err := os.OpenFile(gloablConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		defer fi.Close()
		if err != nil {
			log.Fatal("Error opening file", err)
		} else {
			logBackend := logging.NewLogBackend(fi, "", 0)
			logBackendFormatter := logging.NewBackendFormatter(logBackend, logging.GlogFormatter)
			backends = append(backends, logBackendFormatter)
		}
	}
	if gloablConfiguration.TraefikLogsStdout {
		logBackend := logging.NewLogBackend(os.Stdout, "", 0)
		logBackendFormatter := logging.NewBackendFormatter(logBackend, format)
		backends = append(backends, logBackendFormatter)
	}
	logging.SetBackend(backends...)
	logging.SetLevel(level, "traefik")

	configurationRouter = LoadDefaultConfig(gloablConfiguration)

	// listen new configurations from providers
	go func() {
		for {
			configuration := <-configurationChan
			log.Info("Configuration receveived %+v", configuration)
			if configuration == nil {
				log.Info("Skipping empty configuration")
			} else if reflect.DeepEqual(currentConfiguration, configuration) {
				log.Info("Skipping same configuration")
			} else {
				newConfigurationRouter, err := LoadConfig(configuration, gloablConfiguration)
				if err == nil {
					currentConfiguration = configuration
					configurationRouter = newConfigurationRouter
					srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
					time.Sleep(3 * time.Second)
				} else {
					log.Error("Error loading new configuration, aborted ", err)
				}
			}
		}
	}()

	// configure providers
	if gloablConfiguration.Docker != nil {
		providers = append(providers, gloablConfiguration.Docker)
	}
	if gloablConfiguration.Marathon != nil {
		providers = append(providers, gloablConfiguration.Marathon)
	}
	if gloablConfiguration.File != nil {
		if len(gloablConfiguration.File.Filename) == 0 {
			// no filename, setting to global config file
			gloablConfiguration.File.Filename = *globalConfigFile
		}
		providers = append(providers, gloablConfiguration.File)
	}
	if gloablConfiguration.Web != nil {
		providers = append(providers, gloablConfiguration.Web)
	}
	if gloablConfiguration.Consul != nil {
		providers = append(providers, gloablConfiguration.Consul)
	}

	// start providers
	for _, provider := range providers {
		log.Notice("Starting provider %v %+v", reflect.TypeOf(provider), provider)
		currentProvider := provider
		go func() {
			currentProvider.Provide(configurationChan)
		}()
	}

	goAway := false
	go func() {
		sig := <-sigs
		log.Notice("I have to go... %+v", sig)
		goAway = true
		srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
	}()

	for {
		if goAway {
			break
		}

		// middlewares
		var negroni = negroni.New()
		negroni.Use(metrics)
		negroni.Use(loggerMiddleware)
		//negroni.Use(middlewares.NewCircuitBreaker(oxyLogger))
		//negroni.Use(middlewares.NewRoutes(configurationRouter))
		negroni.UseHandler(configurationRouter)

		srv = &graceful.Server{
			Timeout:          time.Duration(gloablConfiguration.GraceTimeOut) * time.Second,
			NoSignalHandling: true,

			Server: &http.Server{
				Addr:    gloablConfiguration.Port,
				Handler: negroni,
			},
		}

		go func() {
			if len(gloablConfiguration.CertFile) > 0 && len(gloablConfiguration.KeyFile) > 0 {
				srv.ListenAndServeTLS(gloablConfiguration.CertFile, gloablConfiguration.KeyFile)
			} else {
				srv.ListenAndServe()
			}
		}()
		log.Notice("Started")
		<-srv.StopChan()
		log.Notice("Stopped")
	}
}
Beispiel #11
0
// Provide allows the provider to provide configurations to traefik
// using the given configuration channel.
func (provider *WebProvider) Provide(configurationChan chan<- types.ConfigMessage, pool *safe.Pool, _ types.Constraints) error {

	systemRouter := mux.NewRouter()

	// health route
	systemRouter.Methods("GET").Path("/health").HandlerFunc(provider.getHealthHandler)

	// ping route
	systemRouter.Methods("GET").Path("/ping").HandlerFunc(provider.getPingHandler)
	// API routes
	systemRouter.Methods("GET").Path("/api").HandlerFunc(provider.getConfigHandler)
	systemRouter.Methods("GET").Path("/api/version").HandlerFunc(provider.getVersionHandler)
	systemRouter.Methods("GET").Path("/api/providers").HandlerFunc(provider.getConfigHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}").HandlerFunc(provider.getProviderHandler)
	systemRouter.Methods("PUT").Path("/api/providers/{provider}").HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
		if provider.ReadOnly {
			response.WriteHeader(http.StatusForbidden)
			fmt.Fprintf(response, "REST API is in read-only mode")
			return
		}
		vars := mux.Vars(request)
		if vars["provider"] != "web" {
			response.WriteHeader(http.StatusBadRequest)
			fmt.Fprintf(response, "Only 'web' provider can be updated through the REST API")
			return
		}

		configuration := new(types.Configuration)
		body, _ := ioutil.ReadAll(request.Body)
		err := json.Unmarshal(body, configuration)
		if err == nil {
			configurationChan <- types.ConfigMessage{ProviderName: "web", Configuration: configuration}
			provider.getConfigHandler(response, request)
		} else {
			log.Errorf("Error parsing configuration %+v", err)
			http.Error(response, fmt.Sprintf("%+v", err), http.StatusBadRequest)
		}
	})
	systemRouter.Methods("GET").Path("/api/providers/{provider}/backends").HandlerFunc(provider.getBackendsHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/backends/{backend}").HandlerFunc(provider.getBackendHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/backends/{backend}/servers").HandlerFunc(provider.getServersHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/backends/{backend}/servers/{server}").HandlerFunc(provider.getServerHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends").HandlerFunc(provider.getFrontendsHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends/{frontend}").HandlerFunc(provider.getFrontendHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends/{frontend}/routes").HandlerFunc(provider.getRoutesHandler)
	systemRouter.Methods("GET").Path("/api/providers/{provider}/frontends/{frontend}/routes/{route}").HandlerFunc(provider.getRouteHandler)

	// Expose dashboard
	systemRouter.Methods("GET").Path("/").HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
		http.Redirect(response, request, "/dashboard/", 302)
	})
	systemRouter.Methods("GET").PathPrefix("/dashboard/").Handler(http.StripPrefix("/dashboard/", http.FileServer(&assetfs.AssetFS{Asset: autogen.Asset, AssetInfo: autogen.AssetInfo, AssetDir: autogen.AssetDir, Prefix: "static"})))

	// expvars
	if provider.server.globalConfiguration.Debug {
		systemRouter.Methods("GET").Path("/debug/vars").HandlerFunc(expvarHandler)
	}

	go func() {
		var err error
		var negroni = negroni.New()
		if provider.Auth != nil {
			authMiddleware, err := middlewares.NewAuthenticator(provider.Auth)
			if err != nil {
				log.Fatal("Error creating Auth: ", err)
			}
			negroni.Use(authMiddleware)
		}
		negroni.UseHandler(systemRouter)

		if len(provider.CertFile) > 0 && len(provider.KeyFile) > 0 {
			err = http.ListenAndServeTLS(provider.Address, provider.CertFile, provider.KeyFile, negroni)
		} else {
			err = http.ListenAndServe(provider.Address, negroni)
		}

		if err != nil {
			log.Fatal("Error creating server: ", err)
		}
	}()
	return nil
}
Beispiel #12
0
// InitializeService initializes the service with the
// provided config and starts it. The channel returned
// allows the calller to wait for a message from the running
// service. Messages are of type ServiceMessage above.
// It can be used for launching service from tests, etc.
func InitializeService(service Service, config ServiceConfig) (chan ServiceMessage, string, error) {
	err := service.SetConfig(config)
	if err != nil {
		return nil, "", err
	}
	err = service.Initialize()
	if err != nil {
		return nil, "", err
	}
	// Create negroni
	negroni := negroni.New()

	// Add authentication middleware
	negroni.Use(NewAuth())

	// Add content-negotiation middleware.
	// This is an example of using a middleware.
	// This will modify the response header to the
	// negotiated content type, and can then be used as
	// ct := w.Header().Get("Content-Type")
	// where w is http.ResponseWriter
	negroni.Use(NewNegotiator())

	// Unmarshal data from the content-type format
	// into a map
	negroni.Use(NewUnmarshaller())

	routes := service.Routes()
	router := newRouter(routes)

	timeoutMillis := config.Common.Api.RestTimeoutMillis
	var dur time.Duration
	var readWriteDur time.Duration
	if timeoutMillis <= 0 {
		timeoutMillis = DefaultRestTimeout
		dur = DefaultRestTimeout * time.Millisecond
		readWriteDur = (DefaultRestTimeout + ReadWriteTimeoutDelta) * time.Millisecond
		log.Printf("%s: Invalid timeout %d, defaulting to %d\n", service.Name(), timeoutMillis, dur)
	} else {
		timeoutStr := fmt.Sprintf("%dms", timeoutMillis)
		dur, _ = time.ParseDuration(timeoutStr)
		timeoutStr = fmt.Sprintf("%dms", timeoutMillis+ReadWriteTimeoutDelta)
		readWriteDur, _ = time.ParseDuration(timeoutStr)
	}

	log.Printf("%s: Creating TimeoutHandler with %v\n", service.Name(), dur)
	timeoutHandler := http.TimeoutHandler(router, dur, TimeoutMessage)
	negroni.UseHandler(timeoutHandler)

	hostPort := config.Common.Api.GetHostPort()
	log.Println("About to start...")
	ch, addr, err := RunNegroni(negroni, hostPort, readWriteDur)

	if err == nil {
		if addr != hostPort {
			log.Printf("Requested address %s, real %s\n", hostPort, addr)
			idx := strings.LastIndex(addr, ":")
			config.Common.Api.Host = addr[0:idx]
			port, _ := strconv.Atoi(addr[idx+1:])
			port64 := uint64(port)
			config.Common.Api.Port = port64
			// Also register this with root service
			url := fmt.Sprintf("%s/config/%s/port", config.Common.Api.RootServiceUrl, service.Name())
			result := make(map[string]interface{})
			portMsg := PortUpdateMessage{Port: port64}
			client, err := NewRestClient("", timeoutMillis)
			if err != nil {
				return ch, addr, err
			}
			err = client.Post(url, portMsg, &result)
		}
	}
	return ch, addr, err

}
Beispiel #13
0
// LoadConfig returns a new gorilla.mux Route from the specified global configuration and the dynamic
// provider configurations.
func (server *Server) loadConfig(configurations configs, globalConfiguration GlobalConfiguration) (map[string]*serverEntryPoint, error) {
	serverEntryPoints := server.buildEntryPoints(globalConfiguration)
	redirectHandlers := make(map[string]http.Handler)

	backends := map[string]http.Handler{}
	for _, configuration := range configurations {
		frontendNames := sortedFrontendNamesForConfig(configuration)
		for _, frontendName := range frontendNames {
			frontend := configuration.Frontends[frontendName]

			log.Debugf("Creating frontend %s", frontendName)
			fwd, _ := forward.New(forward.Logger(oxyLogger), forward.PassHostHeader(frontend.PassHostHeader))
			// default endpoints if not defined in frontends
			if len(frontend.EntryPoints) == 0 {
				frontend.EntryPoints = globalConfiguration.DefaultEntryPoints
			}
			if len(frontend.EntryPoints) == 0 {
				log.Errorf("No entrypoint defined for frontend %s, defaultEntryPoints:%s. Skipping it", frontendName, globalConfiguration.DefaultEntryPoints)
				continue
			}
			for _, entryPointName := range frontend.EntryPoints {
				log.Debugf("Wiring frontend %s to entryPoint %s", frontendName, entryPointName)
				if _, ok := serverEntryPoints[entryPointName]; !ok {
					return nil, errors.New("Undefined entrypoint: " + entryPointName)
				}
				newServerRoute := &serverRoute{route: serverEntryPoints[entryPointName].httpRouter.GetHandler().NewRoute().Name(frontendName)}
				for routeName, route := range frontend.Routes {
					err := getRoute(newServerRoute, &route)
					if err != nil {
						return nil, err
					}
					log.Debugf("Creating route %s %s", routeName, route.Rule)
				}
				entryPoint := globalConfiguration.EntryPoints[entryPointName]
				if entryPoint.Redirect != nil {
					if redirectHandlers[entryPointName] != nil {
						newServerRoute.route.Handler(redirectHandlers[entryPointName])
					} else if handler, err := server.loadEntryPointConfig(entryPointName, entryPoint); err != nil {
						return nil, err
					} else {
						newServerRoute.route.Handler(handler)
						redirectHandlers[entryPointName] = handler
					}
				} else {
					if backends[frontend.Backend] == nil {
						log.Debugf("Creating backend %s", frontend.Backend)
						var lb http.Handler
						rr, _ := roundrobin.New(fwd)
						if configuration.Backends[frontend.Backend] == nil {
							return nil, errors.New("Undefined backend: " + frontend.Backend)
						}
						lbMethod, err := types.NewLoadBalancerMethod(configuration.Backends[frontend.Backend].LoadBalancer)
						if err != nil {
							configuration.Backends[frontend.Backend].LoadBalancer = &types.LoadBalancer{Method: "wrr"}
						}
						switch lbMethod {
						case types.Drr:
							log.Debugf("Creating load-balancer drr")
							rebalancer, _ := roundrobin.NewRebalancer(rr, roundrobin.RebalancerLogger(oxyLogger))
							lb = rebalancer
							for serverName, server := range configuration.Backends[frontend.Backend].Servers {
								url, err := url.Parse(server.URL)
								if err != nil {
									return nil, err
								}
								log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
								if err := rebalancer.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
									return nil, err
								}
							}
						case types.Wrr:
							log.Debugf("Creating load-balancer wrr")
							lb = rr
							for serverName, server := range configuration.Backends[frontend.Backend].Servers {
								url, err := url.Parse(server.URL)
								if err != nil {
									return nil, err
								}
								log.Debugf("Creating server %s at %s with weight %d", serverName, url.String(), server.Weight)
								if err := rr.UpsertServer(url, roundrobin.Weight(server.Weight)); err != nil {
									return nil, err
								}
							}
						}
						maxConns := configuration.Backends[frontend.Backend].MaxConn
						if maxConns != nil && maxConns.Amount != 0 {
							extractFunc, err := utils.NewExtractor(maxConns.ExtractorFunc)
							if err != nil {
								return nil, err
							}
							log.Debugf("Creating loadd-balancer connlimit")
							lb, err = connlimit.New(lb, extractFunc, maxConns.Amount, connlimit.Logger(oxyLogger))
							if err != nil {
								return nil, err
							}
						}
						// retry ?
						if globalConfiguration.Retry != nil {
							retries := len(configuration.Backends[frontend.Backend].Servers)
							if globalConfiguration.Retry.Attempts > 0 {
								retries = globalConfiguration.Retry.Attempts
							}
							maxMem := int64(2 * 1024 * 1024)
							if globalConfiguration.Retry.MaxMem > 0 {
								maxMem = globalConfiguration.Retry.MaxMem
							}
							lb, err = stream.New(lb,
								stream.Logger(oxyLogger),
								stream.Retry("IsNetworkError() && Attempts() < "+strconv.Itoa(retries)),
								stream.MemRequestBodyBytes(maxMem),
								stream.MaxRequestBodyBytes(maxMem),
								stream.MemResponseBodyBytes(maxMem),
								stream.MaxResponseBodyBytes(maxMem))
							log.Debugf("Creating retries max attempts %d", retries)
							if err != nil {
								return nil, err
							}
						}

						var negroni = negroni.New()
						if configuration.Backends[frontend.Backend].CircuitBreaker != nil {
							log.Debugf("Creating circuit breaker %s", configuration.Backends[frontend.Backend].CircuitBreaker.Expression)
							negroni.Use(middlewares.NewCircuitBreaker(lb, configuration.Backends[frontend.Backend].CircuitBreaker.Expression, cbreaker.Logger(oxyLogger)))
						} else {
							negroni.UseHandler(lb)
						}
						backends[frontend.Backend] = negroni
					} else {
						log.Debugf("Reusing backend %s", frontend.Backend)
					}
					server.wireFrontendBackend(newServerRoute, backends[frontend.Backend])
				}
				err := newServerRoute.route.GetError()
				if err != nil {
					log.Errorf("Error building route: %s", err)
				}
			}
		}
	}
	return serverEntryPoints, nil
}
Beispiel #14
0
func main() {
	kingpin.Parse()
	fmtlog.SetFlags(fmtlog.Lshortfile | fmtlog.LstdFlags)
	var srv *graceful.Server
	var configurationRouter *mux.Router
	var configurationChan = make(chan *Configuration, 10)
	defer close(configurationChan)
	var providers = []Provider{}
	var sigs = make(chan os.Signal, 1)
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	// load global configuration
	gloablConfiguration := LoadFileConfig(*globalConfigFile)

	loggerMiddleware := middlewares.NewLogger(gloablConfiguration.AccessLogsFile)
	defer loggerMiddleware.Close()

	// logging
	level, err := log.ParseLevel(strings.ToLower(gloablConfiguration.LogLevel))
	if err != nil {
		log.Fatal("Error getting level", err)
	}
	log.SetLevel(level)

	if len(gloablConfiguration.TraefikLogsFile) > 0 {
		fi, err := os.OpenFile(gloablConfiguration.TraefikLogsFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
		defer fi.Close()
		if err != nil {
			log.Fatal("Error opening file", err)
		} else {
			log.SetOutput(fi)
			log.SetFormatter(&log.TextFormatter{DisableColors: true, FullTimestamp: true, DisableSorting: true})
		}
	} else {
		log.SetFormatter(&log.TextFormatter{FullTimestamp: true, DisableSorting: true})
	}

	configurationRouter = LoadDefaultConfig(gloablConfiguration)

	// listen new configurations from providers
	go func() {
		for {
			configuration := <-configurationChan
			log.Infof("Configuration receveived %+v", configuration)
			if configuration == nil {
				log.Info("Skipping empty configuration")
			} else if reflect.DeepEqual(currentConfiguration, configuration) {
				log.Info("Skipping same configuration")
			} else {
				newConfigurationRouter, err := LoadConfig(configuration, gloablConfiguration)
				if err == nil {
					currentConfiguration = configuration
					configurationRouter = newConfigurationRouter
					srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
					time.Sleep(3 * time.Second)
				} else {
					log.Error("Error loading new configuration, aborted ", err)
				}
			}
		}
	}()

	// configure providers
	if gloablConfiguration.Docker != nil {
		providers = append(providers, gloablConfiguration.Docker)
	}
	if gloablConfiguration.Marathon != nil {
		providers = append(providers, gloablConfiguration.Marathon)
	}
	if gloablConfiguration.File != nil {
		if len(gloablConfiguration.File.Filename) == 0 {
			// no filename, setting to global config file
			gloablConfiguration.File.Filename = *globalConfigFile
		}
		providers = append(providers, gloablConfiguration.File)
	}
	if gloablConfiguration.Web != nil {
		providers = append(providers, gloablConfiguration.Web)
	}
	if gloablConfiguration.Consul != nil {
		providers = append(providers, gloablConfiguration.Consul)
	}

	// start providers
	for _, provider := range providers {
		log.Infof("Starting provider %v %+v", reflect.TypeOf(provider), provider)
		currentProvider := provider
		go func() {
			currentProvider.Provide(configurationChan)
		}()
	}

	goAway := false
	go func() {
		sig := <-sigs
		log.Infof("I have to go... %+v", sig)
		goAway = true
		srv.Stop(time.Duration(gloablConfiguration.GraceTimeOut) * time.Second)
	}()

	for {
		if goAway {
			break
		}

		// middlewares
		var negroni = negroni.New()
		negroni.Use(metrics)
		negroni.Use(loggerMiddleware)
		//negroni.Use(middlewares.NewCircuitBreaker(oxyLogger))
		//negroni.Use(middlewares.NewRoutes(configurationRouter))
		negroni.UseHandler(configurationRouter)

		srv = &graceful.Server{
			Timeout:          time.Duration(gloablConfiguration.GraceTimeOut) * time.Second,
			NoSignalHandling: true,

			Server: &http.Server{
				Addr:    gloablConfiguration.Port,
				Handler: negroni,
			},
		}

		go func() {
			if len(gloablConfiguration.CertFile) > 0 && len(gloablConfiguration.KeyFile) > 0 {
				err := srv.ListenAndServeTLS(gloablConfiguration.CertFile, gloablConfiguration.KeyFile)
				if err != nil {
					netOpError, ok := err.(*net.OpError)
					if ok && netOpError.Err.Error() != "use of closed network connection" {
						log.Fatal("Error creating server: ", err)
					}
				}
			} else {
				err := srv.ListenAndServe()
				if err != nil {
					netOpError, ok := err.(*net.OpError)
					if ok && netOpError.Err.Error() != "use of closed network connection" {
						log.Fatal("Error creating server: ", err)
					}
				}
			}
		}()
		log.Info("Started")
		<-srv.StopChan()
		log.Info("Stopped")
	}
}