package api import ( "net/http" "github.com/containous/mux" "github.com/containous/traefik/log" "github.com/containous/traefik/middlewares" "github.com/containous/traefik/safe" "github.com/containous/traefik/types" "github.com/containous/traefik/version" thoas_stats "github.com/thoas/stats" "github.com/unrolled/render" ) // Handler expose api routes type Handler struct { EntryPoint string `description:"EntryPoint" export:"true"` Dashboard bool `description:"Activate dashboard" export:"true"` Debug bool `export:"true"` CurrentConfigurations *safe.Safe Statistics *types.Statistics `description:"Enable more detailed statistics" export:"true"` Stats *thoas_stats.Stats `json:"-"` StatsRecorder *middlewares.StatsRecorder `json:"-"` } var ( templatesRenderer = render.New(render.Options{ Directory: "nowhere", }) ) // AddRoutes add api routes on a router func (p Handler) AddRoutes(router *mux.Router) { if p.Debug { DebugHandler{}.AddRoutes(router) } router.Methods(http.MethodGet).Path("/api").HandlerFunc(p.getConfigHandler) router.Methods(http.MethodGet).Path("/api/providers").HandlerFunc(p.getConfigHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}").HandlerFunc(p.getProviderHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends").HandlerFunc(p.getBackendsHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends/{backend}").HandlerFunc(p.getBackendHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends/{backend}/servers").HandlerFunc(p.getServersHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/backends/{backend}/servers/{server}").HandlerFunc(p.getServerHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends").HandlerFunc(p.getFrontendsHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends/{frontend}").HandlerFunc(p.getFrontendHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends/{frontend}/routes").HandlerFunc(p.getRoutesHandler) router.Methods(http.MethodGet).Path("/api/providers/{provider}/frontends/{frontend}/routes/{route}").HandlerFunc(p.getRouteHandler) // health route router.Methods(http.MethodGet).Path("/health").HandlerFunc(p.getHealthHandler) version.Handler{}.AddRoutes(router) if p.Dashboard { DashboardHandler{}.AddRoutes(router) } } func getProviderIDFromVars(vars map[string]string) string { providerID := vars["provider"] // TODO: Deprecated if providerID == "rest" { providerID = "web" } return providerID } func (p Handler) getConfigHandler(response http.ResponseWriter, request *http.Request) { currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) err := templatesRenderer.JSON(response, http.StatusOK, currentConfigurations) if err != nil { log.Error(err) } } func (p Handler) getProviderHandler(response http.ResponseWriter, request *http.Request) { providerID := getProviderIDFromVars(mux.Vars(request)) currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, provider) if err != nil { log.Error(err) } } else { http.NotFound(response, request) } } func (p Handler) getBackendsHandler(response http.ResponseWriter, request *http.Request) { providerID := getProviderIDFromVars(mux.Vars(request)) currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, provider.Backends) if err != nil { log.Error(err) } } else { http.NotFound(response, request) } } func (p Handler) getBackendHandler(response http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) providerID := getProviderIDFromVars(vars) backendID := vars["backend"] currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { if backend, ok := provider.Backends[backendID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, backend) if err != nil { log.Error(err) } return } } http.NotFound(response, request) } func (p Handler) getServersHandler(response http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) providerID := getProviderIDFromVars(vars) backendID := vars["backend"] currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { if backend, ok := provider.Backends[backendID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, backend.Servers) if err != nil { log.Error(err) } return } } http.NotFound(response, request) } func (p Handler) getServerHandler(response http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) providerID := getProviderIDFromVars(vars) backendID := vars["backend"] serverID := vars["server"] currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { if backend, ok := provider.Backends[backendID]; ok { if server, ok := backend.Servers[serverID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, server) if err != nil { log.Error(err) } return } } } http.NotFound(response, request) } func (p Handler) getFrontendsHandler(response http.ResponseWriter, request *http.Request) { providerID := getProviderIDFromVars(mux.Vars(request)) currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, provider.Frontends) if err != nil { log.Error(err) } } else { http.NotFound(response, request) } } func (p Handler) getFrontendHandler(response http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) providerID := getProviderIDFromVars(vars) frontendID := vars["frontend"] currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { if frontend, ok := provider.Frontends[frontendID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, frontend) if err != nil { log.Error(err) } return } } http.NotFound(response, request) } func (p Handler) getRoutesHandler(response http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) providerID := getProviderIDFromVars(vars) frontendID := vars["frontend"] currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { if frontend, ok := provider.Frontends[frontendID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, frontend.Routes) if err != nil { log.Error(err) } return } } http.NotFound(response, request) } func (p Handler) getRouteHandler(response http.ResponseWriter, request *http.Request) { vars := mux.Vars(request) providerID := getProviderIDFromVars(vars) frontendID := vars["frontend"] routeID := vars["route"] currentConfigurations := p.CurrentConfigurations.Get().(types.Configurations) if provider, ok := currentConfigurations[providerID]; ok { if frontend, ok := provider.Frontends[frontendID]; ok { if route, ok := frontend.Routes[routeID]; ok { err := templatesRenderer.JSON(response, http.StatusOK, route) if err != nil { log.Error(err) } return } } } http.NotFound(response, request) } // healthResponse combines data returned by thoas/stats with statistics (if // they are enabled). type healthResponse struct { *thoas_stats.Data *middlewares.Stats } func (p *Handler) getHealthHandler(response http.ResponseWriter, request *http.Request) { health := &healthResponse{Data: p.Stats.Data()} if p.StatsRecorder != nil { health.Stats = p.StatsRecorder.Data() } err := templatesRenderer.JSON(response, http.StatusOK, health) if err != nil { log.Error(err) } }