package api import ( "fmt" log "github.com/sirupsen/logrus" "net/http" ) const tokenMissingMsg = "api token is empty or has not been set. exiting" // API is the http server responsible for serving the HTTP API endpoints type API struct { Token string hasHandlers bool } // New is a factory function creating a new API instance func New(token string) *API { return &API{ Token: token, hasHandlers: false, } } // RequireToken is wrapper around http.HandleFunc that checks token validity func (api *API) RequireToken(fn http.HandlerFunc) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Authorization") != fmt.Sprintf("Bearer %s", api.Token) { log.Errorf("Invalid token \"%s\"", r.Header.Get("Authorization")) log.Debugf("Expected token to be \"%s\"", api.Token) return } log.Println("Valid token found.") fn(w, r) } } // RegisterFunc is a wrapper around http.HandleFunc that also sets the flag used to determine whether to launch the API func (api *API) RegisterFunc(path string, fn http.HandlerFunc) { api.hasHandlers = true http.HandleFunc(path, api.RequireToken(fn)) } // RegisterHandler is a wrapper around http.Handler that also sets the flag used to determine whether to launch the API func (api *API) RegisterHandler(path string, handler http.Handler) { api.hasHandlers = true http.Handle(path, api.RequireToken(handler.ServeHTTP)) } // Start the API and serve over HTTP. Requires an API Token to be set. func (api *API) Start(block bool) error { if !api.hasHandlers { log.Debug("Watchtower HTTP API skipped.") return nil } if api.Token == "" { log.Fatal(tokenMissingMsg) } log.Info("Watchtower HTTP API started.") if block { runHTTPServer() } else { go func() { runHTTPServer() }() } return nil } func runHTTPServer() { log.Info("Serving HTTP") log.Fatal(http.ListenAndServe(":8080", nil)) }