2017-11-09 16:12:04 +01:00
package api
import (
2018-11-14 10:18:03 +01:00
"io"
2017-11-09 16:12:04 +01:00
"net/http"
"github.com/containous/mux"
2018-11-14 10:18:03 +01:00
"github.com/containous/traefik/config"
2017-11-09 16:12:04 +01:00
"github.com/containous/traefik/log"
"github.com/containous/traefik/safe"
"github.com/containous/traefik/types"
"github.com/containous/traefik/version"
2018-05-25 15:10:04 +02:00
"github.com/elazarl/go-bindata-assetfs"
2018-11-14 10:18:03 +01:00
thoasstats "github.com/thoas/stats"
2017-11-09 16:12:04 +01:00
"github.com/unrolled/render"
)
2018-11-14 10:18:03 +01:00
// ResourceIdentifier a resource identifier
type ResourceIdentifier struct {
ID string ` json:"id" `
Path string ` json:"path" `
}
// ProviderRepresentation a provider with resource identifiers
type ProviderRepresentation struct {
Routers [ ] ResourceIdentifier ` json:"routers,omitempty" `
Middlewares [ ] ResourceIdentifier ` json:"middlewares,omitempty" `
Services [ ] ResourceIdentifier ` json:"services,omitempty" `
}
// RouterRepresentation extended version of a router configuration with an ID
type RouterRepresentation struct {
* config . Router
ID string ` json:"id" `
}
// MiddlewareRepresentation extended version of a middleware configuration with an ID
type MiddlewareRepresentation struct {
* config . Middleware
ID string ` json:"id" `
}
// ServiceRepresentation extended version of a service configuration with an ID
type ServiceRepresentation struct {
* config . Service
ID string ` json:"id" `
}
2017-11-09 16:12:04 +01:00
// Handler expose api routes
type Handler struct {
2018-11-14 10:18:03 +01:00
EntryPoint string
Dashboard bool
Debug bool
2017-11-09 16:12:04 +01:00
CurrentConfigurations * safe . Safe
2018-11-14 10:18:03 +01:00
Statistics * types . Statistics
Stats * thoasstats . Stats
// StatsRecorder *middlewares.StatsRecorder // FIXME stats
DashboardAssets * assetfs . AssetFS
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
var templateRenderer jsonRenderer = render . New ( render . Options { Directory : "nowhere" } )
type jsonRenderer interface {
JSON ( w io . Writer , status int , v interface { } ) error
}
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
// Append add api routes on a router
func ( p Handler ) Append ( router * mux . Router ) {
2017-11-09 16:12:04 +01:00
if p . Debug {
2018-11-14 10:18:03 +01:00
DebugHandler { } . Append ( router )
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
router . Methods ( http . MethodGet ) . Path ( "/api/providers" ) . HandlerFunc ( p . getProvidersHandler )
2017-11-20 09:40:03 +01:00
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}" ) . HandlerFunc ( p . getProviderHandler )
2018-11-14 10:18:03 +01:00
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}/routers" ) . HandlerFunc ( p . getRoutersHandler )
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}/routers/{router}" ) . HandlerFunc ( p . getRouterHandler )
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}/middlewares" ) . HandlerFunc ( p . getMiddlewaresHandler )
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}/middlewares/{middleware}" ) . HandlerFunc ( p . getMiddlewareHandler )
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}/services" ) . HandlerFunc ( p . getServicesHandler )
router . Methods ( http . MethodGet ) . Path ( "/api/providers/{provider}/services/{service}" ) . HandlerFunc ( p . getServiceHandler )
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
// FIXME stats
2017-11-09 16:12:04 +01:00
// health route
2018-11-14 10:18:03 +01:00
//router.Methods(http.MethodGet).Path("/health").HandlerFunc(p.getHealthHandler)
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
version . Handler { } . Append ( router )
2017-11-09 16:12:04 +01:00
if p . Dashboard {
2018-11-14 10:18:03 +01:00
DashboardHandler { Assets : p . DashboardAssets } . Append ( router )
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getProvidersHandler ( rw http . ResponseWriter , request * http . Request ) {
// FIXME handle currentConfiguration
if p . CurrentConfigurations != nil {
currentConfigurations , ok := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
if ! ok {
rw . WriteHeader ( http . StatusOK )
return
}
var providers [ ] ResourceIdentifier
for name := range currentConfigurations {
providers = append ( providers , ResourceIdentifier {
ID : name ,
Path : "/api/providers/" + name ,
} )
}
err := templateRenderer . JSON ( rw , http . StatusOK , providers )
if err != nil {
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
}
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getProviderHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
}
var routers [ ] ResourceIdentifier
for name := range provider . Routers {
routers = append ( routers , ResourceIdentifier {
ID : name ,
Path : "/api/providers/" + providerID + "/routers" ,
} )
}
var services [ ] ResourceIdentifier
for name := range provider . Services {
services = append ( services , ResourceIdentifier {
ID : name ,
Path : "/api/providers/" + providerID + "/services" ,
} )
}
var middlewares [ ] ResourceIdentifier
for name := range provider . Middlewares {
middlewares = append ( middlewares , ResourceIdentifier {
ID : name ,
Path : "/api/providers/" + providerID + "/middlewares" ,
} )
}
providers := ProviderRepresentation { Routers : routers , Middlewares : middlewares , Services : services }
err := templateRenderer . JSON ( rw , http . StatusOK , providers )
2017-11-09 16:12:04 +01:00
if err != nil {
2018-11-14 10:18:03 +01:00
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getRoutersHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
var routers [ ] RouterRepresentation
for name , router := range provider . Routers {
routers = append ( routers , RouterRepresentation { Router : router , ID : name } )
}
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
err := templateRenderer . JSON ( rw , http . StatusOK , routers )
if err != nil {
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getRouterHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
routerID := mux . Vars ( request ) [ "router" ]
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
}
router , ok := provider . Routers [ routerID ]
if ! ok {
http . NotFound ( rw , request )
return
}
err := templateRenderer . JSON ( rw , http . StatusOK , router )
if err != nil {
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getMiddlewaresHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
var middlewares [ ] MiddlewareRepresentation
for name , middleware := range provider . Middlewares {
middlewares = append ( middlewares , MiddlewareRepresentation { Middleware : middleware , ID : name } )
}
err := templateRenderer . JSON ( rw , http . StatusOK , middlewares )
if err != nil {
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getMiddlewareHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
middlewareID := mux . Vars ( request ) [ "middleware" ]
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
middleware , ok := provider . Middlewares [ middlewareID ]
if ! ok {
http . NotFound ( rw , request )
return
}
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
err := templateRenderer . JSON ( rw , http . StatusOK , middleware )
if err != nil {
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
2017-11-09 16:12:04 +01:00
}
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getServicesHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
2017-11-09 16:12:04 +01:00
2018-11-14 10:18:03 +01:00
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
var services [ ] ServiceRepresentation
for name , service := range provider . Services {
services = append ( services , ServiceRepresentation { Service : service , ID : name } )
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
err := templateRenderer . JSON ( rw , http . StatusOK , services )
if err != nil {
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
}
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
func ( p Handler ) getServiceHandler ( rw http . ResponseWriter , request * http . Request ) {
providerID := mux . Vars ( request ) [ "provider" ]
serviceID := mux . Vars ( request ) [ "service" ]
currentConfigurations := p . CurrentConfigurations . Get ( ) . ( config . Configurations )
provider , ok := currentConfigurations [ providerID ]
if ! ok {
http . NotFound ( rw , request )
return
}
service , ok := provider . Services [ serviceID ]
if ! ok {
http . NotFound ( rw , request )
return
2017-11-09 16:12:04 +01:00
}
2018-11-14 10:18:03 +01:00
err := templateRenderer . JSON ( rw , http . StatusOK , service )
2017-11-09 16:12:04 +01:00
if err != nil {
2018-11-14 10:18:03 +01:00
log . FromContext ( request . Context ( ) ) . Error ( err )
http . Error ( rw , err . Error ( ) , http . StatusInternalServerError )
2017-11-09 16:12:04 +01:00
}
}